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

Solved AGym 100712AWho Is The Winner
Solved BGym 100712BRock-Paper-Scissors
Solved CGym 100712CStreet Lamps
Solved DGym 100712DAlternating Strings
Solved EGym 100712EEpic Professor
Solved FGym 100712FTravelling Salesman
Solved GGym 100712GHeavy Coins
Solved HGym 100712HBridges
Solved IGym 100712IBahosain and Digits
Solved JGym 100712JCandy
Solved KGym 100712KRuntime Error
Solved LGym 100712LAlternating 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\n",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\n",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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值