zoukankan      html  css  js  c++  java
  • Codeforces Round #650 (Div. 3)

    打的 vp,花了 1h 30min 切了前 6 个,后来花了 20min 把最后一题也切掉了.   

    难度不大,但是想要进前 10 的话手速还是要快一点.   

    A - Short Substrings

    观察一下字符串,然后发现相同的保留一个就行. 

    #include <bits/stdc++.h>   
    #define N 1087   
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std; 
    char str[N];  
    void solve() {  
        scanf("%s",str+1); 
        int n=strlen(str+1); 
        printf("%c",str[1]);    
        for(int i=2;i<=n-2;i+=2) {  
            printf("%c",str[i]); 
        }
        printf("%c
    ",str[n]);  
    }
    int main() { 
        // setIO("input");  
        int T; 
        scanf("%d",&T);   
        while(T--) solve();  
        return 0; 
    }
    

      

    B - Even Array

    判断合不合法很简单,然后最小步数显然就是偶数/奇数不合法的位置个数.    

    #include <bits/stdc++.h>    
    #define N 1008  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;  
    int a[N],c0,c1,c2; 
    void solve() { 
        int n; 
        scanf("%d",&n); 
        c0=c1=c2=0; 
        for(int i=0;i<n;++i) {
            scanf("%d",&a[i]); 
            if(a[i]&1) ++c1; 
            else ++c0;  
            if((a[i]&1)!=(i&1)) {
                ++c2;    
            }
        }   
        if(c0!=(n+1)/2) printf("-1
    "); 
        else printf("%d
    ",c2/2);  
    }
    int main() {
        // setIO("input");   
        int T; 
        scanf("%d",&T); 
        while(T--) solve(); 
        return 0; 
    }
    

      

    C - Social Distance

    可以用差分数组维护 0 的连通块.   

    连通块内贪心去填 1 就行,也就是 $frac{len}{(k+1)}+(len \% (k+1) != 0)$  

    #include <bits/stdc++.h>     
    #define N 200009  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    char str[N];     
    int a[N];  
    void solve() {  
        int n,k; 
        scanf("%d%d",&n,&k);  
        scanf("%s",str+1);    
        for(int i=1;i<=n+3;++i) a[i]=0; 
        for(int i=1;i<=n;++i) {  
            if(str[i]=='1') {    
                a[max(1,i-k)]++;    
                a[min(i+k,n)+1]--;                  
            }
        }   
        int pre0=0,mx=0; 
        for(int i=1;i<=n;++i) 
        {
            a[i]+=a[i-1];  
            if(!a[i]) ++pre0;    
            else {  
                mx+=pre0/(k+1);   
                if(pre0%(k+1)) ++mx; 
                pre0=0; 
            }
        }  
        mx+=pre0/(k+1);
        if(pre0%(k+1)) ++mx;     
        printf("%d
    ",mx);  
    }
    int main() {  
        // setIO("input");   
        int T; 
        scanf("%d",&T); 
        while(T--) solve(); 
        return 0; 
    }
    

      

    D - Task On The Board

    从大到小依次考虑,显然最大的 b[i]=0,然后次大的 b[i]=该位置到所有最大的距离.  

    这样可以判断序列中元素的 rank,然后再贪心去填字母就行了.

    #include <bits/stdc++.h>    
    #define N 53   
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;      
    char str[N]; 
    int n,m,a[N],RK[N],cnt[N],num[N],ou[N];      
    void solve() {   
        memset(RK,0,sizeof(RK));  
        memset(cnt,0,sizeof(cnt)); 
        memset(num,0,sizeof(num));  
        memset(ou,0,sizeof(ou));   
        scanf("%s",str+1);  
        n=strlen(str+1);        
        for(int i=1;i<=n;++i) ++num[str[i]-'a'];   
        scanf("%d",&m); 
        for(int i=1;i<=m;++i) scanf("%d",&a[i]);     
        int bu=0; 
        for(int i=1;;++i) {  
            int flag=0;    
            for(int j=1;j<=m;++j) {         
                if(RK[j]) continue;   
                int cur=0; 
                for(int t=1;t<=m;++t) {  
                    if(RK[t]&&RK[t]<i) 
                        cur+=abs(t-j);  
                }  
                if(cur==a[j]) RK[j]=i,flag=1,++cnt[i];       
            }
            if(!flag) break;     
            bu=i;   
        }       
        int c=1;  
        for(int i=27;i>=0;--i) {  
            if(num[i]>=cnt[c]) {  
                ou[c]=i;   
                ++c;     
            }
            if(c>bu) break;  
        }
        for(int i=1;i<=m;++i) {  
            printf("%c",'a'+ou[RK[i]]);  
        }
        printf("
    ");  
    }
    int main() {  
        // setIO("input");   
        int T; 
        scanf("%d",&T); 
        while(T--) solve();  
        return 0; 
    }
    

      

    E - Necklace Assembly

    循环节为 $k$,意味着序列可以分成若干段,每段长度都为 k,且所有段相等.     

    由于每段长度固定,所以可以二分段数.   

    然后由于这里的循环节可能非常大,所以不妨分解 k 的因数,然后对每个因数求一下答案,最后取 max.   

    #include <bits/stdc++.h>    
    #define N 2008  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int cnt[30],n,K; 
    char S[N];   
    int check(int x,int cur) {   
        int tmp=0; 
        for(int i=0;i<27;++i) {  
            tmp+=cnt[i]/x;  
        }
        return tmp>=cur;     
    }
    int cal(int p) { 
        int l=1,r=n,ans=0; 
        while(l<=r) { 
            int mid=(l+r)>>1;   
            if(check(mid,p)) ans=mid,l=mid+1; 
            else r=mid-1; 
        }  
        return ans*p;   
    }
    void solve() {   
        memset(cnt,0,sizeof(cnt));  
        scanf("%d%d",&n,&K);          
        scanf("%s",S+1); 
        for(int i=1;i<=n;++i) ++cnt[S[i]-'a'];   
        int ans=0;  
        for(int i=1;i<=n;++i) { 
            if(K%i==0) {
                ans=max(ans,cal(i));       
            }
        }  
        printf("%d
    ",ans);  
    }
    int main() { 
        // setIO("input");  
        int T; 
        scanf("%d",&T); 
        while(T--) solve();  
        return 0; 
    }
    

      

    F2 - Flying Sort (Hard Version)

    不难发现留下的是值域连续的一段,然后将值域两端分别扔到前后.   

    那么问题就转化成求极长值域连续的段数长度.   

    所有数互不相同显然很好求.  

    对于出现数字相同的情况,不难发现构成一定是 零散 + 所有值严格取到 + 零散的形式.  

    即只有最小和最大值可以不都取完,中间的必须都取完.   

    这个直接用 DP 求就行. 

    要特判中间没有严格取到的情况.  

    #include <bits/stdc++.h>    
    #define N 1000009  
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int f[N],a[N],A[N],fst[N],lst[N],pos[N],num[N],Num[N];    
    void solve() {          
        int n;   
        scanf("%d",&n); 
        for(int i=1;i<=n;++i) {
            scanf("%d",&a[i]); 
            A[i]=a[i]; 
        }          
        sort(A+1,A+1+n);      
        int m=unique(A+1,A+1+n)-A-1;                         
        for(int i=1;i<=n+233;++i) f[i]=pos[i]=fst[i]=lst[i]=num[i]=Num[i]=0;   
        for(int i=1;i<=n;++i) a[i]=lower_bound(A+1,A+1+m,a[i])-A,++Num[a[i]];         
        for(int i=1;i<=n;++i) {   
            if(!fst[a[i]]) 
                fst[a[i]]=i;     
            lst[a[i]]=i;  
        }     
        int mx=0; 
        for(int i=1;i<=n;++i) {    
            f[i]=1;  
            if(fst[a[i]]==i) {  
                if(lst[a[i]-1]<i) f[i]=max(f[i],f[lst[a[i]-1]]+1);       
                f[i]=max(f[i],num[a[i]-1]+1);    
            }
            else f[i]=max(f[i],f[pos[a[i]]]+1);    
            ++num[a[i]];  
            pos[a[i]]=i;                   
            if(lst[a[i]]==i) mx=max(mx,f[i]+Num[a[i]+1]-num[a[i]+1]);       
            mx=max(mx,num[a[i]]+Num[a[i]+1]-num[a[i]+1]);   
        }         
        printf("%d
    ",n-mx);  
    }    
    int main() { 
        // setIO("input");  
        int T;  
        scanf("%d",&T); 
        while(T--) solve();  
        return 0; 
    }
    

      

  • 相关阅读:
    VS2008正式版序列号
    清空SQL Server数据库中所有的用户表
    [原创]JavaScript调用Button的服务器端事件
    动态加载枚举 到 DropdownList
    [转载]静态构造函数
    SQL 事务 [两种]
    Jpg文件格式[参考]
    Delegate Event
    javascript 操作cookie类
    [共享]一个文件上传的控件,绝对是精品源码
  • 原文地址:https://www.cnblogs.com/guangheli/p/13204609.html
Copyright © 2011-2022 走看看