18春季训练01-3/11 2015 ACM Amman Collegiate Programming Contest

Solved   A Gym 100712A Who Is The Winner
Solved   B Gym 100712B Rock-Paper-Scissors
Solved   C Gym 100712C Street Lamps
Solved   D Gym 100712D Alternating Strings
Solved   E Gym 100712E Epic Professor
Solved   F Gym 100712F Travelling Salesman
Solved   G Gym 100712G Heavy Coins
Solved   H Gym 100712H Bridges
Solved   I Gym 100712I Bahosain and Digits
Solved   J Gym 100712J Candy
Solved   K Gym 100712K Runtime Error
Solved   L Gym 100712L Alternating Strings II


2015 ACM Amman Collegiate Programming Contes

训练赛01,icpc赛制五小时,难度三星,最终AC:8/12 打得很菜

A  找到最高分数同时罚时最小的就行

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
struct node {
    int a,b;
    string name;
}x[maxn];
int cmp(node a,node b){
    if(a.a==b.a) return a.b<b.b;
    else return a.a>b.a;
}
int main(){
// #define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
//        memset(x,0,sizeof x);
        read(n);
        for(int i=0;i<n;i++){
        cin>>x[i].name>>x[i].a>>x[i].b;
        }
        sort(x,x+n,cmp);
        cout<<x[0].name<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

B 先预处理前缀和,再枚举2个分界点,复杂度n^2

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
char s[maxn];
int s1[maxn],s2[maxn],s3[maxn];
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        cin>>n>>(s+1);
        for(int i=1;i<=n;i++){
            s1[i]=s1[i-1]+(s[i]=='R');
            s2[i]=s2[i-1]+(s[i]=='P');
            s3[i]=s3[i-1]+(s[i]=='S');
        }
        int ans=0;
        int mx=0;
        for(int i=0;i<=n;i++){
            for(int j=i;j<=n;j++){
                int x=s3[i]+(s1[j]-s1[i])+(s2[n]-s2[j]);
                x-=(s2[i])+(s3[j]-s3[i])+(s1[n]-s1[j]);
                if(x>0){
                    ans++;
                }
            }
        }
        cout<<ans<<endl;
    }
#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

C 跑两遍,注意用2个数组,不要重复计算了,方法很多,可以黑暗长度大于1就直接点亮后面一个

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
char s[maxn];
char s2[maxn];
int ans;
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

  read(casn);
  while(casn--){
      cin>>n>>(s+1);
      int ans=0;
      memset(s2,'.',sizeof s2);
      for(int i=1;i<=n;i++){
          if(s[i]=='*') s2[i]=s2[i+1]=s2[i-1]='*';
      }
      for(int i=1;i<=n;i++){
          if(s2[i]==s2[i+1]&&s2[i]==s2[i+2]&&s2[i]=='.'){
              s2[i+1]=s2[i]=s2[i+2]='*';
              ans++;
          }else if(s2[i]=='.'){
                  s2[i+1]=s2[i]=s2[i+2]='*';
              ans++;
          }
      }
      cout<<ans<<endl;
  }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}

D (补)

定义dp[i]为把i合法分割的最小花费

dp[i]可以直接转移到dp[i-1]+1

然后遍历(i-k)到i,如果出现连续,从连续处到(i-k)都可以转移到dp[i],花费为1

数据小,复杂度n^2可过

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
char s[maxn];
int dp[maxn];
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,k);
        scanf("%s",s+1);
        memset(dp,INF,sizeof dp);
        dp[0]=-1;
        for(int i=1;i<=n;i++){
            dp[i]=min(dp[i],dp[i-1]+1);
            int flag=0;
            for(int j=i-1;j&&i-j+1<=k;j--){
                if(s[j]==s[j+1]) flag=1;
                if(flag) {
                    dp[i]=min(dp[i],dp[j-1]+1);
                }
            }
        }
        cout<<dp[n]<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

E 所有人的中,加上(100-最小值)不低于50的有多少

/**********************
*@Name:
*
*@Author: Nervending
*@Describtion:
*@DateTime:
***********************/
#include <bits/stdc++.h>
#define show(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
bool cmp(int &a,int &b)
{
    return  a>b;
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n);
        for(int i=0;i<n;i++){
            read(num[i]);
        }
        sort(num,num+n,cmp);
        int tmp=100-num[0];
        int ans=0;
        for(int i=0;i<n;i++){
            if(num[i]+tmp>=50) ans++;
        }
        printf("%d
",ans);
    }
    
#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

F 给一个无向连通图,求最小瓶颈树的最大边是多少

简单推导,可知最小瓶颈树就是最小生成树,就是求最小生成树的最大边

(一开始想成了求任意两点之间的路径中的最大边...)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int root[maxn];
struct node{
    int from,to,cost;
}e[maxm];
bool cmp(node &a,node &b){
    return a.cost<b.cost;
}
int ans,t;
int find(int now){
    if(now==root[now])return now;
    else {
        return root[now]=find(root[now]);
    }
}
#define same(a,b) (find(a)==find(b))
void unite(int a,int b){
    a=find(a);
    b=find(b);
    if(a==b)return ;
    else root[a]=b;
}
void init(){
    for(int i=0;i<maxn;i++){
        root[i]=i;
    }
    memset(e,0,sizeof e);
}
void kruskal(){
    sort(e,e+m,cmp);
    for(int i=0;i<m;i++){
        node t=e[i];
        if(!same(t.from,t.to)){
            unite(t.from,t.to);
            ans=max(t.cost,ans);
        }
    }
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,m);
        init();
        int cnt=0;
        for(int i=0;i<m;i++){
            int a,b,c;
            read(a,b,c);
            e[cnt++]=(node){a,b,c};
            e[cnt++]=(node){b,a,c};
        }
        m=cnt;
        ans=0;
        kruskal();
        cout<<ans<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

G 排个序之后直接暴力枚举所有的可能性,枚举过程中的选择用位压缩就行

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,m);
        memset(num,0xc0,sizeof num);
        for(int i=0;i<n;i++){
            read(num[i]);
        }
        sort(num,num+n);
        int ans=0;
        for(int i=1;i<1<<n;i++){
            int s=0,mn=INF,cnt=0,mx=0,flag=1;
            for(int j=0;j<n;j++){
                if((i>>j)&1)
                    s+=num[j],mx=max(num[j],mx),cnt++;
            }
            if(s>=m){
                for(int j=0;j<n;j++){
                    if((i>>j)&1) if(s-num[j]>=m) flag=0;
                }
                if(flag) ans=max(ans,cnt);
            }
            
        }
        cout<<ans<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

H (补)

把图进行双连通分量把图缩成一颗树,在新图中用两次dfs找到树的直径,然后答案就是强连通分量的数量-直径-1

(好久没写tarjan+缩点,懵逼了)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
struct node {int to,cost,next;}e[maxm],e2[maxm];int head[maxn],head2[maxn],nume,nume2;
void add(int a,int b,int c=1,node *eg=e,int &ne=nume,int hd[]=head){eg[++ne]=(node){b,c,hd[a]};hd[a]=ne;}
int casn,n,m,k;
int low[maxn],dfn[maxn],stk[maxn];
int ins[maxn];
int top,numc,numd,belong[maxn];

void tjdfs(int now,int pre) {
    dfn[now]=low[now]=++numd;
    stk[++top]=now;
    ins[now]=1;
    for(int i=head[now]; i; i=e[i].next) {
        int to=e[i].to;
        if(to==pre)continue;
        if(ins[to]==0) tjdfs(to,now);
        low[now]=min(low[now],low[to]);
    }
    if(low[now]==dfn[now]) {
        numc++;
        do {
            belong[stk[top]]=numc;
            ins[stk[top]]=-1;
        } while(stk[top--]!=now);
    }
}
void tjmake(){
    for(int i=1;i<=n;i++){
        int a=belong[i];
        for(int j=head[i];j;j=e[j].next){
            int to=e[j].to;
            int b=belong[to];
            if(a==b) continue;
            add(a,b,1,e2,nume2,head2);
            add(b,a,1,e2,nume2,head2);
        }
    }
}
inline void tjinit(){
    numc=nume2=numd=0;
    top=-1;
    memset(ins,0,sizeof ins);
    memset(dfn,0,sizeof dfn);
    memset(head2,0,sizeof head);
    memset(belong,0,sizeof belong);
    memset(low,0,sizeof low);
    memset(stk,0,sizeof stk);
}
inline void tarjan(){
    tjinit();
    for(int i=1;i<=n;i++) if(ins[i]==0){
         tjdfs(i,-1);
    }
    tjmake();
}
int vis[maxn],cnt=0,pos,ans;
void dfs(int now,int dep=0){
    vis[now]=1;
    if(dep>cnt){
        cnt=dep;
        pos=now;
    }
    for(int i=head2[now];i;i=e2[i].next){
        int to=e2[i].to;
        if(!vis[to]) dfs(to,dep+1);
    }
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    read(casn);
    while(casn--){
        read(n,m);
        memset(head,0,sizeof head);
        nume=0;
        for(int i=0;i<m;i++){
            int a,b;read(a,b);
            add(a,b);
            add(b,a);
        }
        tarjan();
        memset(vis,0,sizeof vis);
        cnt=0;
        pos=1;
        dfs(1);
        memset(vis,0,sizeof vis);
        cnt=0;
        dfs(pos);
        cout<<numc-cnt-1<<endl;;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

I (补)

暴力枚举最终到达的数字,由于只需要找到最大可行解,但是可行解不具有单调性,所以只能从n开始遍历k长

复杂度10*n^2,一开始10*n^3的算法T了,

然后用一个数组和一个变量维护改变量,复杂度可以降阶,就ac了

#include <bits/stdc++.h>
using namespace std;
const int maxn=3e2+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
#define show(x) cout<<#x<<"="<<x<<endl
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m;
char s[maxn];
int add[maxn];
int t[maxn];
int main(){
#define test
#ifdef test
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        scanf("%s",s+1);
        int f=0;
        int len=strlen(s+1);
        for(int k=len;k>1;k--){
            for(int i=0;i<10;i++){
                memset(add,0,sizeof add);
                for(int j=1;j<=len;j++) t[j]=s[j]-'0';
                int tmp=0;
                for(int j=1;j+k-1<=len;j++){
                        tmp-=add[max(j-k,0)];
                        int y=0;
                        t[j]=(t[j]+tmp)%10;
                        if(t[j]==i) continue;
                        if(i>t[j]) y=(i-t[j]);
                        else y=(i+10-t[j]);
                        add[j]=y;
                        t[j]=i;
                        tmp+=y;
                }
                int flag=1;
                for(int j=len-k+2;j<=len;j++){
                    tmp-=add[max(j-k,0)];
                    if((t[j]+tmp)%10!=i){
                        flag=0;
                        break;
                    }
                }
                if(flag){
                    printf("%d
",k);
                    f=1;
                    break;
                }
            }
            if(f) break;
        }
        if(f==0) puts("1");
    }

#ifdef test
    fclose(stdin);
//    fclose(stdout);
//    system("out.txt");
#endif
    return 0;
}
View Code

J 桶排序记录蜡烛数量和年龄人数,遍历统计即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn],s[maxn];
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,m);
        int mx=0,mx2=0;
        memset(num,0,sizeof num);
        memset(s,0,sizeof s);
        for(int i=0;i<n;i++){
            int k;read(k);
            s[k]++;
            mx2=max(k,mx2);
        }

        for(int i=0;i<m;i++) {
            int k;read(k);
            num[k]++;
            mx=max(k,mx);
        }
        int cnt=0;
        int ans=1;
        for(int i=5;i<=mx2;i++){
            while(cnt<=mx&&num[cnt]<s[i]) cnt++;
            if(cnt>mx){
                ans=0;
                break;
            }
            if(s[i]) cnt++;

        }
        cout<<(ans?"YES":"NO")<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

K 标记数组记录是否存在,然后遍历数组,是否k/x存在

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int vis[maxn];
int num[maxn];
int main(){
// #define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,k);
        memset(vis,0,sizeof vis);
        for(int i=0;i<n;i++){
            read(num[i]);
            vis[num[i]]++;
        }
        sort(num,num+n);
        int flag=0;
        for(int i=0;i<n&&num[i]*num[i]<=k&&flag==0;i++){
            if(num[i]==0) continue;
            if(k%num[i]==0){
                if(num[i]*num[i]==k&&vis[num[i]]>=2){
                    cout<<num[i]<<' '<<num[i]<<endl;
                    flag=1;
                }
                else if(num[i]*num[i]!=k&&vis[k/num[i]]){
                    cout<<num[i]<<' '<<k/num[i]<<endl;
                    flag=1;
                }
            }
        }
        if(!flag) cout<<-1<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code

L (补)

把D题的数据范围扩大了1000倍

解法依然是DP,n^2无法过 考虑n^2以下的算法

思路:

1.外层循环->无法减少 

2.找到(i-k)到i之间的最早连续位置需要低于O(n)->预处理找到i之前的不连续长度达到O(1)询问

3.找到(dp[i-k]到dp[i-pos])之间的最小值,pos为最后一个连续处也需要低于O(n)->线段树维护DP数组,O(logn)查询最小值

最后在单点更新dp[i]处的答案即可

复杂度nlogn

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
char s[maxn];
int ans;
int lst[maxn<<3];
int num[maxn];
#define mid ((l+r)>>1)
int rmin(int s,int t,int l=0,int r=n,int now=1){
    if(l>r||t<l||s>r) return INF;
    if(s<=l&&t>=r) return lst[now];
    return min(rmin(s,t,l,mid,now<<1),rmin(s,t,mid+1,r,now<<1|1));
}
void upd(int pos,int x,int l=0,int r=n,int now=1){
    if(l>r||pos<l||pos>r) return;
    lst[now]=min(x,lst[now]);
    if(l==r) return;
    upd(pos,x,l,mid,now<<1);
    upd(pos,x,mid+1,r,now<<1|1);
}
int main(){
//#define test
#ifdef test
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif

    read(casn);
    while(casn--){
        read(n,k);
        scanf("%s",s+1);
        ans=0;
        memset(lst,INF,sizeof lst);
        memset(num,0,sizeof num);
        #define show(x) cout<<#x<<"="<<x<<endl
        for(int i=1;i<=n;i++){
             if(s[i]!=s[i-1]) num[i]=num[i-1]+1;
             else num[i]=1;
        }
        upd(0,0);
        for(int i=1;i<=n;i++){
            ans++;
            if(i-num[i]>=max(i-k,0)+1)
                ans=min(ans,rmin(max(i-k,0),i-num[i]-1)+1);
            upd(i,ans);
        }
        cout<<ans-1<<endl;
    }

#ifdef test
    fclose(stdin);
    fclose(stdout);
    system("out.txt");
#endif
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/nervendnig/p/8573233.html