zoukankan      html  css  js  c++  java
  • Codeforces Round #376 Div.2

    A:题意:给定一个由字母表组成的首尾相接的环,环上有一个指针,最初指向字母a,每次可以顺时针或逆时针旋转一格,例如a顺时针转到z,逆时针转到b,然后问转出给定字符串最少需要转多少次。

    思路:模拟。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 
     8 char s[1000];
     9 
    10 int main(){
    11     scanf("%s",s+1);
    12     int now=0,ans=0;
    13     for (int i=1;i<=strlen(s+1);i++){
    14         int t=s[i]-'a';
    15         ans+=min(abs(t-now),26-abs(t-now));
    16         now=t;
    17     }
    18     printf("%d
    ",ans);
    19     return 0;
    20 }
    A

    B:题意:一共有n天,然后每天需要买恰好ai个披萨,对于每天披萨的购买只有两种方式,要么一次买两个披萨,要么一次为今天买一个披萨同时为明天也买一个披萨,不能有其余任何的购买方式,且这两种购买方式可以使用无限次数,问是否每天都能恰好买到ai个。

    思路:显然对于第i天的披萨,如果ai是偶数,则直接用第一种购买方式,因为这显然合法且对后面不产生影响,若ai是奇数,则应该先用第一种购买方式买到只剩一个,然后再用第二种购买方式,然后ai+1--,如果存在一个ai<0(包括an+1),则说明不合法,否则合法。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define maxn 200005
     8 
     9 int n;
    10 int a[maxn];
    11 
    12 int main(){
    13     scanf("%d",&n);
    14     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    15     for (int i=1;i<=n;i++){
    16         if (a[i]<0){puts("NO");return 0;}
    17         if (a[i]&1) a[i]=0,a[i+1]--;
    18     }
    19     if (a[n+1]<0) puts("NO");else puts("YES");
    20     return 0;
    21 }
    B

    C:题意:一共n只袜子,m天,k种颜色,然后给出每一只袜子的初始颜色,然后m天给定每一天穿哪双袜子,然后要给最少的袜子染色使得每一天穿的袜子颜色相同。

    思路:对于每一天穿的一双袜子看成两个点,然后连边,那么显然对于一条边连接的两个点颜色是要相同的,也就是说属于一个连通块内的所有点的颜色是要相同的,于是对于每一个连通块找出出现次数最多的颜色,然后用size减去它就是该连通块对答案的贡献。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define maxn 200005
     8 
     9 int n,m,k,tot,tmp,top,size,ans;
    10 int col[maxn],now[maxn],pre[maxn*10],son[maxn*10],cnt[maxn],stack[maxn];
    11 bool vis[maxn];
    12 
    13 void add(int a,int b){
    14     son[++tot]=b;
    15     pre[tot]=now[a];
    16     now[a]=tot;
    17 }
    18 
    19 void link(int a,int b){
    20     add(a,b),add(b,a);
    21 }
    22 
    23 void dfs(int x){
    24     size++;
    25     if (!cnt[col[x]]) stack[++top]=col[x];
    26     cnt[col[x]]++,tmp=max(tmp,cnt[col[x]]);
    27     for (int p=now[x];p;p=pre[p])
    28         if (!vis[son[p]]) vis[son[p]]=1,dfs(son[p]);
    29 }
    30 
    31 int main(){
    32     scanf("%d%d%d",&n,&m,&k);
    33     for (int i=1;i<=n;i++) scanf("%d",&col[i]);
    34     for (int i=1,a,b;i<=m;i++) scanf("%d%d",&a,&b),link(a,b);
    35     for (int i=1;i<=n;i++)
    36         if (!vis[i]){
    37             vis[i]=1;
    38             size=0,tmp=0,dfs(i),ans+=size-tmp;
    39             for (int j=1;j<=top;j++) cnt[stack[j]]=0;
    40             top=0;
    41         }
    42     printf("%d
    ",ans);
    43     return 0;
    44 }
    C

    D:题意:一共n个字符串,c种颜色,然后给出每一个字符串的长度(记为li)再给出每一个字符串(注意n<=500000,li<=500000,sigma(li)<=1000000),每一个字符串之间用空格隔开,然后你可以顺时针(也仅可以顺时针)置换,即对于任意一个字符串的任意一个数字,如果顺时针置换一次,将由1变成2,2变成3...c变成1,并且如果置换一次,所有的数字均会按照上述规则进行变换,问转几次恰好能使所有字符串按照字典序排列。、

    思路:显然转c次就是一个循环,因此答案一定是[0,c-1]的一个数,或是0,然后因为数据范围的问题是不可能全部存下来然后离线处理的,因此每读入一个字符串就要在线处理,记录前一个字符串(记为pre[])和后一个字符串(记为now[]),然后一定要使后一个字符串比前一个字符串的字典序大,即找到第一个不同字符,然后如果pre[i]>now[i],那么显然一定要让pre[i]转过c,而使now[i]不能转过c,于是此处的转动的范围即[c-pre[i]+1,c-now[i]],否则如果pre[i]<now[i],那么显然要么不让now[i]转过c,要么pre[i]也转过c,那么此处转动的范围即[0,c-now[i]]∪[c-pre[i]+1,c-1],然后每一次都属于范围之内的元素即答案,用线段树维护,或差分一下均可。然后还要注意一个细节,就是如果pre[i]和now[i]前面所有的元素都相同且pre[i]的长度要大于now[i]的长度显然就无解。

    PS:好气啊,比赛时这道题写了好久,结果还因为打错一个变量名GG了,然后后面两道大水题。。。。。。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 using namespace std;
     7 #define maxn 500005
     8 
     9 int n,c,ans;
    10 int now[maxn],pre[maxn];
    11 bool first=1;
    12 
    13 struct segment_tree{
    14     struct treenode{
    15         bool can;
    16     }tree[maxn*4];
    17     void build(int p,int l,int r){
    18         tree[p].can=1;
    19         if (l==r) return;
    20         int mid=(l+r)>>1;
    21         build(p<<1,l,mid);
    22         build(p<<1|1,mid+1,r);
    23     }
    24     void change(int p,int l,int r,int x,int y){
    25         if (!tree[p].can) return;
    26         if (x<=l && r<=y){
    27             tree[p].can=0;
    28             return;
    29         }
    30         int mid=(l+r)>>1;
    31         if (x<=mid) change(p<<1,l,mid,x,y);
    32         if (y>mid) change(p<<1|1,mid+1,r,x,y);
    33     }
    34     void query(int p,int l,int r){
    35         if (!tree[p].can) return;
    36         if (l==r){if (first) ans=l,first=0;return;}
    37         int mid=(l+r)>>1;
    38         query(p<<1,l,mid),query(p<<1|1,mid+1,r);
    39     }
    40 }T;
    41 
    42 int main(){
    43     scanf("%d%d",&n,&c);int prelen=0;
    44     T.build(1,0,c-1);
    45     for (int i=1;i<=n;i++){
    46         int nowlen=0;
    47         if (i==1){
    48             scanf("%d",&nowlen),prelen=nowlen;
    49             for (int j=1;j<=nowlen;j++) scanf("%d",&now[j]),pre[j]=now[j];
    50             continue;
    51         }
    52         scanf("%d",&nowlen);
    53         for (int j=1;j<=nowlen;j++) scanf("%d",&now[j]);
    54         for (int j=1;j<=prelen;j++){
    55             if (j>nowlen/*WA=>prelen*/){T.change(1,0,c-1,0,c-1);break;}
    56             if (pre[j]!=now[j]){
    57                 if (pre[j]>now[j]) T.change(1,0,c-1,0,c-pre[j]),T.change(1,0,c-1,c-now[j]+1,c-1);
    58                 else T.change(1,0,c-1,c-now[j]+1,c-pre[j]);
    59                 break;
    60             }
    61         }
    62         prelen=nowlen;
    63         for (int j=1;j<=nowlen;j++) pre[j]=now[j];
    64     }
    65     ans=-1;
    66     T.query(1,0,c-1);
    67     printf("%d
    ",ans);
    68     return 0;
    69 }
    D

    E:题意:一共n张贴纸,然后每一张上写有一个数字,每次两人从左边选出至少两个数字(至多可以选完),然后将这些贴纸撕去,再贴一张新的贴纸代表所选的数字之和,然后收益就是所选的所有数字之和,问两人均采取最好策略的情况下,先手收益最多能比后手多多少(如果比后手收益少x则输出-x),数字可能为负。

    思路:用f[i]表示从i开始玩(也就是前i个已经被缩为一张了)先手与后手的最大差距,然后显然f[i]一定是由某个j转移过来的,因为当前先手一定是将i到j这一段缩成一个数字,然后f[i]=max{sum[j]-f[j]},令f[i]表示真正的先手(后手也是一样,因为都是最优策略),此处的f[j]虽然表示的先手实际上是真正的后手,然后f[j]=j到n中真正后手的收益-j到n中真正先手的收益,因而sum[j]-f[j]=sum[i]+j到n中真正先手的收益-j到n中真正后手的收益,于是这个转移方程就很显然了,然后直接用ans表示sum[j]-f[j]的最大值,然后用ans=max{sum[i]-ans,ans}转移即可。时间复杂度O(n)。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define maxn 200005
     8 
     9 int n;
    10 int a[maxn];
    11 long long sum[maxn];
    12 
    13 int main(){
    14     scanf("%d",&n);
    15     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    16     for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];long long ans=sum[n];
    17     for (int i=n-1;i>1;i--) ans=max(ans,sum[i]-ans);
    18     printf("%lld
    ",ans);
    19     return 0;
    20 }
    E

    F:题意:一共n个数,选定一个数使得其余所有数均为该数的倍数,然后该数大小不能变,其余数的大小均减小以满足是选定数的倍数,问减小后的序列之和的最大值是多少。

    思路:枚举选定哪一个数i,然后显然可以分块,记录i*j到(i+1)*j-1中一共多少个数,这些数显然一定会变成i*j,然后统计答案即可,时间复杂度O(n*log(n)),最坏时间复杂度O(n*sqrt(n))。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define maxn 500005
     8 
     9 int n;
    10 int a[maxn],f[maxn];
    11 long long ans;
    12 
    13 int main(){
    14     scanf("%d",&n);
    15     for (int i=1,x;i<=n;i++) scanf("%d",&x),a[x]++;
    16     for (int i=200000;i;i--) f[i]=f[i+1]+a[i];
    17     for (int i=1;i<=200000;i++)
    18         if (a[i]){
    19             long long sum=0;
    20             for (int j=i;j<=200000;j+=i) sum+=1ll*(f[j]-f[i+j])*j;
    21             ans=max(ans,sum);
    22         }
    23     printf("%lld
    ",ans);
    24     return 0;
    25 }
    F
  • 相关阅读:
    SSR 第二篇,搭建Vue SSR程序
    SSR 第一篇,搭建简单的SSR程序
    数组的所有方法整理学习
    CustomEvent 使用
    VUE CSS module
    eslint Expected linebreaks to be 'LF' but found 'CRLF'
    利用Object.freeze() 提升性能
    vue 项目开启gzip 压缩和性能优化
    [转]Ext Grid控件的配置与方法
    ExtJS renderer(转)
  • 原文地址:https://www.cnblogs.com/DUXT/p/5968578.html
Copyright © 2011-2022 走看看