• 题解Codeforces Round #617 (Div. 3) (CF1296)


     A:有奇数有偶数肯定行,只有奇数如果有奇数个也行,否则不行。

     1 #include<stdio.h>
     2 #define it register int
     3 #define ct const int
     4 #define il inline
     5 const int N=1000005;
     6 int T,n,a[N],o1,o2;
     7 int main(){
     8 scanf("%d",&T);
     9 while(T--){
    10     scanf("%d",&n);
    11     o1=o2=0;
    12     for(it i=1;i<=n;++i) scanf("%d",&a[i]),o1+=(a[i]&1),o2+=(!(a[i]&1));
    13     if(o1&&o2) puts("YES");
    14     else if(!o2&&(o1&1)) puts("YES");
    15     else puts("NO");
    16 }
    17 return 0;
    18 }
    19     
    A

    B:不浪费肯定最好啊,每次把10的整数倍那部分挖出来/10即可。

     1 #include<stdio.h>
     2 #define it register int
     3 #define ct const int
     4 #define il inline
     5 int T,n,o1,o2,ans;
     6 int main(){ 
     7     scanf("%d",&T);
     8     while(T--){
     9         scanf("%d",&n),ans=0;
    10         while(n>=10)
    11             ans+=(n/10)*10,n=n%10+n/10;
    12         printf("%d
    ",ans+n);
    13     }
    14     return 0;
    15 }
    B

    C:判断一下这个位置之前有没有出现过,用两次相减取最小即可。

     1 #include<stdio.h>
     2 #include<map>
     3 #define it register int
     4 #define ct const int
     5 #define il inline
     6 using namespace std;
     7 const int N=1000005;
     8 int T,n,idi,idj;
     9 char s[N];
    10 map<int,map<int,int> > a;
    11 int main(){ 
    12     scanf("%d",&T);
    13     while(T--){
    14         scanf("%d",&n),scanf("%s",s+2),a.clear(),++n;
    15         it x=1,y=1,ans=2e9;a[1][1]=1;
    16         for(it i=2;i<=n;++i){
    17             if(s[i]=='L') --x;
    18             if(s[i]=='R') ++x;
    19             if(s[i]=='U') ++y;
    20             if(s[i]=='D') --y;
    21             if(a[x][y]&&i-a[x][y]<ans) idi=a[x][y],ans=i-idi,idj=i;
    22             a[x][y]=i;
    23         }
    24         if(ans==2e9) puts("-1");
    25         else printf("%d %d
    ",idi,idj-1);
    26     }
    27     return 0;
    28 }
    C

    D:计算一下对于每个a[i]得到需要付出的代价,就假设前面两个人一直轮流,最后剩下的a[i]∈[1,x+y],然后除x上取整,排序,从小到大选就可以了。为什么从小到大选是对的:因为每个贡献都是1。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define it register int
     4 using namespace std;
     5 const int N=1000005;
     6 int n,x,y,k,a[N],ans; 
     7 int main(){
     8     scanf("%d%d%d%d",&n,&x,&y,&k);
     9     for(it i=1;i<=n;++i){
    10         scanf("%d",&a[i]),a[i]%=(x+y);
    11         if(!a[i]) a[i]=x+y;
    12         a[i]=(a[i]<=x?0:(a[i]-x-1)/x+1);
    13     }
    14     std::sort(a+1,a+1+n);
    15     for(it i=1;k>=a[i]&&i<=n;k-=a[i],++ans,++i);
    16     printf("%d",ans);
    17     return 0;
    18 }
    D

    E1:先判断有没有解:由于只有两种颜色,所以看看以i为结尾的下降子序列长度是否>2,>2就无解。然后处理整个串,只考虑后一个比前面的大,不断地往前换,并且交换颜色。相等颜色就继承上一个的。

     1 #include<stdio.h>
     2 #define it register int
     3 #define il inline
     4 const int N=100005;
     5 char s[N];
     6 int n,col[N],f[N];
     7 il void spc(char &p,char &q){char x=p;p=q,q=x;}
     8 il void spi(int &p,int &q){int x=p;p=q,q=x;}
     9 int main(){
    10     scanf("%d%s",&n,s+1);
    11     it i,j,now,flag=0;
    12     s[0]=(char)127;
    13     for(i=1;i<=n;i++)
    14         for(j=0;j<i;j++)
    15             if(s[i]<s[j]){
    16                 f[i]=(f[j]+1>f[i]?f[j]+1:f[i]);
    17                 if(f[i]>2) {flag=1;break;}
    18             }
    19     if(flag) return puts("NO"),0;
    20     for(i=2;i<n;++i)
    21         if(s[i-1]>s[i]&&s[i]>s[i+1]&&s[i-1]>s[i+1]) return puts("NO"),0;
    22     puts("YES");s[0]=0;
    23     for(i=1;i<=n;++i){
    24         now=0;
    25         if(s[i]==s[i-1]) col[i]=now=col[i-1];
    26         if(s[i]<s[i-1]){
    27             col[i]=now=col[i-1]^1,j=i;
    28             while(j&&s[j]<s[j-1]) spc(s[j],s[j-1]),spi(col[j],col[j-1]),--j;
    29         }
    30         printf("%d",now);
    31     }
    32     return 0;
    33 }
    E1

    E2:由上题的下降子序列启发,其实可以证明需要覆盖整个序列的最小非递减序列数等于最小递减子序列的长度。直接dp即可。

     1 #include<stdio.h>
     2 #define it register int
     3 #define ct const int
     4 #define il inline
     5 #define Max(a,b) (a>b?a:b)
     6 const int N=1000005;
     7 int n,dp[N],f[N],ans;
     8 char s[N];
     9 int main(){
    10     scanf("%d%s",&n,s+1);it i,j;
    11     for(i=1;i<=n;++i){
    12         dp[i]=1;
    13         for(j=s[i]-'a'+1;j<26;++j)
    14             dp[i]=Max(dp[i],f[j]+1);
    15         f[s[i]-'a']=Max(f[s[i]-'a'],dp[i]),ans=Max(ans,f[s[i]-'a']);
    16     }
    17     printf("%d
    ",ans);
    18     for(i=1;i<=n;++i) printf("%d ",dp[i]);
    19     return 0;
    20 }
    E2

    F:把读入进来的路径以及路径上的最小权值从大到小排序,先覆盖大的再覆盖小的。如果有一次整条路径都覆盖不了了,说明这条路径上的最小值肯定不存在。对于解任意的输出一个极大值就好了。注意用儿子的权值代替父亲和儿子连边的边权(因为父亲是唯一的)

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define it register int
     4 #define ct const int
     5 #define il inline
     6 const int N=1000005;
     7 int h[N],nxt[N],adj[N],t,u,v,pos[N],lnk[N],fa[N],d[N],id,val[N],m,n;
     8 struct ky{
     9     int u,v,w;
    10     bool operator < (const ky&p)const{return w>p.w;}
    11 }a[N];
    12 namespace io{
    13     il char nc(){
    14         static char buf[100000],*p1=buf,*p2=buf;
    15         return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
    16     }
    17     template <class I> 
    18     il void fr(I &num){
    19         num=0;register char c=nc();it p=1;
    20         while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc();
    21         while(c>='0'&&c<='9') num=num*10+c-'0',c=nc();
    22         num*=p;
    23     } 
    24 }
    25 using io ::fr;
    26 void add(){nxt[++t]=h[u],h[u]=t,adj[t]=v,pos[t]=id,nxt[++t]=h[v],h[v]=t,adj[t]=u,pos[t]=id;}
    27 il void dfs(ct x){
    28     d[x]=d[fa[x]]+1;
    29     for(it i=h[x],j;i;i=nxt[i])
    30         if((j=adj[i])!=fa[x])
    31             fa[j]=x,lnk[pos[i]]=j,dfs(j);
    32 }
    33 int main(){
    34     fr(n);it i;
    35     for(i=1;i<n;++i) fr(u),fr(v),id=i,add();
    36     dfs(1),fr(m);
    37     for(i=1;i<=m;++i) fr(a[i].u),fr(a[i].v),fr(a[i].w);
    38     std::sort(a+1,a+1+m);
    39     register bool fl;
    40     for(i=1;i<=m;++i){
    41         u=a[i].u,v=a[i].v,fl=0;
    42         if(d[u]<d[v]) u+=v,v=u-v,u-=v;
    43         while(d[u]^d[v]){
    44             if((!val[u])||val[u]==a[i].w) val[u]=a[i].w,fl=1;
    45             u=fa[u];
    46         }
    47         while(u^v){
    48             if((!val[u])||val[u]==a[i].w) val[u]=a[i].w,fl=1;
    49             if((!val[v])||val[v]==a[i].w) val[v]=a[i].w,fl=1;
    50             u=fa[u],v=fa[v];
    51         }
    52         if(!fl) return puts("-1"),0;
    53     }
    54     for(i=1;i<n;++i) printf("%d ",!val[lnk[i]]?1000000:val[lnk[i]]);
    55     return 0;
    56 }
    F
  • 相关阅读:
    Socket编程模式
    Asp.Net Core
    TensorFlow文本与序列的深度模型
    Net
    XSS分析及预防(转)
    MyCAT部署及实现读写分离(转)
    如何搭建NTP服务(转)
    如何搭建DNS服务(转)
    如何高效地向Redis插入大量的数据(转)
    Android 通过广播启动另一个应用的Activity
  • 原文地址:https://www.cnblogs.com/Kylin-xy/p/tijieCF1296.html
Copyright © 2020-2023  润新知