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

    A. Two distinct points

    题意:每次询问给你l1,r1,l2,r2,让你从区间[l1,r1]和区间[l2,r2]中各选出1个整数,使得这2个数不相同,输入保证l1<r1,l2<r2(也就是没有区间是只有1个数的)

    题解:第一个区间选l1,然后判断l2是否等于l1,不等于就输出,等于就输出r(因为r2不可能等于l2)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int T,l1,r1,l2,r2;
     4 int main()
     5 {
     6     scanf("%d",&T);
     7     while (T--)
     8     {
     9         scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
    10         printf("%d ",l1);
    11         if (l1!=l2) printf("%d
    ",l2);else printf("%d
    ",r2);
    12     }
    13 }
    View Code

    B. Divisors of Two Integers

    题意:我们有2个数x,y,现在我们把他们所有的因数都写出来(不去重),例如6和12的就是,1,2,3,6,1,2,3,4,6,12 

            现在给你这个因数序列,让你反求x,y是多少,题目保证因子大小<=1e4

    题解:我们显然可以发现,整个序列里最大的那个数一定是x(我们约定x>=y),找出x,然后再把x的所有因子剔除,剩下最大的就是y了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,x,f[12000];
     4 int main()
     5 {
     6     scanf("%d",&n);
     7     int y=-1;
     8     for (int i=1;i<=n;i++)
     9     {
    10         scanf("%d",&x);
    11         f[x]++;
    12         y=max(y,x);
    13     }
    14     for (int i=y;i>=1;i--) if (y%i==0) f[i]--;
    15     for (int i=y;i>=1;i--)
    16          if (f[i]==1) {printf("%d %d",y,i);break;}
    17 }
    View Code

    C. Nice Garland

    题意:给你一个字符串,只由'R','G','B',三种字母构成,现在定义一个好串是满足,相同字母之间的位置差是3的非0倍数,

             也就是这3个字母形成一个循环,问你把原序列改成一个好串最少需要改几次,任意给出一种方案

    题解:由于最近相同字母的位置差只可能是3,所以这个循环只有3!=6种,我们枚举这6种串,看哪一种少即可

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int n,ans,a[7];
      4 char s[200005];
      5 int main()
      6 {
      7     scanf("%d",&n);
      8     scanf("%s",s+1);
      9     for (int i=1;i<=n;i++)
     10     {
     11         if (i%3==1) if (s[i]!='R') a[1]++;
     12         if (i%3==2) if (s[i]!='G') a[1]++;
     13         if (i%3==0) if (s[i]!='B') a[1]++;
     14     }
     15     for (int i=1;i<=n;i++)
     16     {
     17         if (i%3==1) if (s[i]!='R') a[2]++;
     18         if (i%3==2) if (s[i]!='B') a[2]++;
     19         if (i%3==0) if (s[i]!='G') a[2]++;
     20     }    
     21     for (int i=1;i<=n;i++)
     22     {
     23         if (i%3==1) if (s[i]!='B') a[3]++;
     24         if (i%3==2) if (s[i]!='G') a[3]++;
     25         if (i%3==0) if (s[i]!='R') a[3]++;
     26     }    
     27     for (int i=1;i<=n;i++)
     28     {
     29         if (i%3==1) if (s[i]!='B') a[4]++;
     30         if (i%3==2) if (s[i]!='R') a[4]++;
     31         if (i%3==0) if (s[i]!='G') a[4]++;
     32     }    
     33     for (int i=1;i<=n;i++)
     34     {
     35         if (i%3==1) if (s[i]!='G') a[5]++;
     36         if (i%3==2) if (s[i]!='B') a[5]++;
     37         if (i%3==0) if (s[i]!='R') a[5]++;
     38     }    
     39     for (int i=1;i<=n;i++)
     40     {
     41         if (i%3==1) if (s[i]!='G') a[6]++;
     42         if (i%3==2) if (s[i]!='R') a[6]++;
     43         if (i%3==0) if (s[i]!='B') a[6]++;
     44     }    
     45     int ans=2000000;
     46     for (int i=1;i<=6;i++)
     47     {
     48         ans=min(ans,a[i]);
     49     }
     50     cout<<ans<<endl;
     51     if (ans==a[1]) 
     52     {
     53         for (int i=1;i<=n;i++)
     54         {
     55             if (i%3==1) printf("R");
     56             if (i%3==2) printf("G");
     57             if (i%3==0) printf("B");
     58         }
     59     }else
     60     if (ans==a[2]) 
     61     {
     62         for (int i=1;i<=n;i++)
     63         {
     64             if (i%3==1) printf("R");
     65             if (i%3==2) printf("B");
     66             if (i%3==0) printf("G");
     67         }
     68     }else
     69     if (ans==a[3]) 
     70     {
     71         for (int i=1;i<=n;i++)
     72         {
     73             if (i%3==1) printf("B");
     74             if (i%3==2) printf("G");
     75             if (i%3==0) printf("R");
     76         }
     77     }else
     78     if (ans==a[4]) 
     79     {
     80         for (int i=1;i<=n;i++)
     81         {
     82             if (i%3==1) printf("B");
     83             if (i%3==2) printf("R");
     84             if (i%3==0) printf("G");
     85         }
     86     }else
     87     if (ans==a[5]) 
     88     {
     89         for (int i=1;i<=n;i++)
     90         {
     91             if (i%3==1) printf("G");
     92             if (i%3==2) printf("B");
     93             if (i%3==0) printf("R");
     94         }
     95     }else
     96     if (ans==a[6]) 
     97     {
     98         for (int i=1;i<=n;i++)
     99         {
    100             if (i%3==1) printf("G");
    101             if (i%3==2) printf("R");
    102             if (i%3==0) printf("B");
    103         }
    104     }            
    105 }
    View Code

    D. Diverse Garland

    题意:还是给你一个只由'R','G','B'构成的字符串,现在的目标串是相邻的字母不同,还是问你至少改几次,任意给一种方案

    题解:扫一次字符串,如果第i个字母和第i-1个字母一样,那么就看i+1的字母是什么,

             如果s[i]=s[i-1]=s[i+1]就把s[i]改成其他2个任意中的一个,如果不等于,那就改成除了s[i-1]和s[i+1]的另外一个

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,ans,a[7];
     4 char s[200005];
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     scanf("%s",s+1);
     9     s[n+1]=s[n];
    10     for (int i=2;i<=n;i++)
    11     {
    12         if (s[i]==s[i-1])
    13         {
    14             if (s[i]=='B' && s[i+1]=='G') ans++,s[i]='R';else
    15             if (s[i]=='B' && s[i+1]=='R') ans++,s[i]='G';else
    16             if (s[i]=='B' && s[i+1]=='B') ans++,s[i]='G';else
    17             if (s[i]=='R' && s[i+1]=='G') ans++,s[i]='B';else
    18             if (s[i]=='R' && s[i+1]=='B') ans++,s[i]='G';else
    19             if (s[i]=='R' && s[i+1]=='R') ans++,s[i]='G';else
    20             if (s[i]=='G' && s[i+1]=='B') ans++,s[i]='R';else
    21             if (s[i]=='G' && s[i+1]=='R') ans++,s[i]='B';else    
    22             if (s[i]=='G' && s[i+1]=='G') ans++,s[i]='B';    
    23         }    
    24     }
    25     printf("%d
    ",ans);
    26     for (int i=1;i<=n;i++) printf("%c",s[i]);    
    27 }
    View Code

    E1. Array and Segments (Easy version)

    题意:给你n(300)个数,还有m(300)个区间,你可以选择其中的某些区间(也可以不选),选到的区间里的每个数都减1,

            问如何选才能使,最后的序列里最大值-最小值最大

    题解:我们显然可以发现,如果我们选择的区间覆盖了最后的最小值且没覆盖最大值,那我们的ans++,

                                          如果覆盖了最大值且没有覆盖最小值,那我们的ans--,

                                          如果都覆盖了,或者都没覆盖,那我们的ans一点影响也没有

          那我们发现其实,只要这个区间覆盖了最后的最小值,那么选这个区间就不亏

          所以我们可以枚举最后的最小值是谁,然后覆盖的所有区间都选上,最后得到最优答案

          时间复杂度是n*m*n的,如果使用差分统计则是n*n的

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,a[505],id,ans,l[505],r[505],f[505],w[505],ansy,b[505];
     4 int main()
     5 {
     6     int why=0;
     7     scanf("%d%d",&n,&m);
     8     for (int i=1;i<=n;i++) 
     9     {
    10         scanf("%d",&b[i]);
    11     }
    12     for (int i=1;i<=m;i++)
    13             scanf("%d%d",&l[i],&r[i]);
    14     for (int id=1;id<=n;id++)
    15     {
    16         for (int i=1;i<=n;i++) a[i]=b[i]; 
    17         ans=0;
    18         for (int i=1;i<=m;i++)
    19         {    
    20             if (l[i]<=id && r[i]>=id) 
    21             {
    22                 for (int j=l[i];j<=r[i];j++) a[j]--;
    23                 ans++;
    24                 f[ans]=i;
    25             }
    26         }
    27         int tmin=5000000,tmax=-5000000;
    28         for (int i=1;i<=n;i++)
    29         {
    30             tmin=min(tmin,a[i]);
    31             tmax=max(tmax,a[i]);
    32         }    
    33         if (tmax-tmin>why)
    34         {
    35             why=tmax-tmin;
    36             ansy=ans;
    37             for (int i=1;i<=ans;i++) w[i]=f[i];
    38         }
    39     }
    40     printf("%d
    %d
    ",why,ansy);
    41     for (int i=1;i<=ansy;i++)
    42     {
    43         printf("%d ",w[i]);
    44     }
    45 }
    View Code

    E2. Array and Segments (Hard version)

    题意:还是和刚刚的E1一样,只不过现在我们的n是1e5的了,m还是300

            我们从刚刚的差分想起走,差分的意思是,在我们枚举了最后的最小值位置之后,看哪些区间可以被选择,此时用差分对这个区间进行减1的操作

            然后再全部扫一次数组,记录最大值和最小值,所以是n*n的

            最后的这次扫,只为了最值,却在循环里又浪费了一次n,可以从这里出发想到,

            如果我们用线段树来维护最大值最小值不就行了,枚举最后的最小值位置后,再枚举m次区间操作,看起来复杂度变成了n*m*logn

            但是实际写的时候你会发现,由于你每次枚举后,都要重新建树,这里还有一个代价,所以这样甚至还不如差分了!

            我们继续考虑继承,不难想到,我们枚举的时候,从i-1变到i的区间并不多(就是只包含i-1却不包含i的区间不会多,这意味着所有的也不超过300)

            那我们每次枚举后,可以先把只包含i-1的区间,重新+1,加回去,再操作以i开头的区间[i,x]们,这样就避免了重复重新建树

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define M 305 
      5 int n,m,a[N],l[M],r[M],ans[N];
      6 vector<int>add[N],sub[N];
      7 struct node
      8 {
      9     int l,r,maxx, minn, lazy;
     10 } tree[N*4];
     11 void push_up(int o)
     12 {
     13     tree[o].maxx=max(tree[o*2].maxx,tree[o*2+1].maxx);
     14     tree[o].minn=min(tree[o*2].minn,tree[o*2+1].minn);
     15 }
     16 void push_down(int o)
     17 {
     18     if (tree[o].l!=tree[o].r)
     19     {
     20         tree[o*2].maxx+=tree[o].lazy;tree[o*2].minn+=tree[o].lazy;
     21         tree[o*2+1].maxx+=tree[o].lazy;tree[o*2+1].minn+=tree[o].lazy;
     22         tree[o*2].lazy+=tree[o].lazy;
     23         tree[o*2+1].lazy+=tree[o].lazy;
     24     }
     25     tree[o].lazy=0;
     26 }
     27 void build(int o,int l,int r)
     28 {
     29     tree[o].l=l;
     30     tree[o].r=r;
     31     if (l==r)
     32     {
     33         tree[o].maxx=a[l];
     34         tree[o].minn=a[l];
     35         tree[o].lazy=0;
     36         return ;
     37     } 
     38     int mid=(l+r)/2;
     39     build(o*2,l,mid);
     40     build(o*2+1,mid+1,r);
     41     push_up(o);
     42 }
     43 
     44 void up(int o,int l,int r,int x)
     45 {
     46     if (tree[o].lazy!=0) push_down(o);
     47     tree[o].maxx+=x;
     48     tree[o].minn+=x;
     49     if (tree[o].l==l && tree[o].r==r)
     50     {
     51         tree[o].lazy+=x;
     52         return ;
     53     }
     54     int mid=(tree[o].l+tree[o].r)/2;
     55     if (r<=mid) up(o*2,l,r,x);
     56     else if(l>mid) up(o*2+1,l,r,x);
     57     else
     58     {
     59         up(o*2,l,mid,x);up(o*2+1,mid+1,r,x);
     60     }
     61     push_up(o);
     62 }
     63 int ask_max(int o,int l,int r)
     64 {
     65     if (tree[o].lazy) push_down(o);
     66     if (tree[o].l==l && tree[o].r==r) return tree[o].maxx;
     67     int mid=(tree[o].l + tree[o].r)/2,why;
     68     if (r<=mid) why=ask_max(o*2,l,r);
     69     else if(l>mid) why=ask_max(o*2+1,l,r);
     70     else why=max(ask_max(o*2,l,mid),ask_max(o*2+1,mid+1,r));
     71     return why;
     72 }
     73 int ask_min(int o,int l,int r)
     74 {
     75     if (tree[o].lazy) push_down(o);
     76     if (tree[o].l==l && tree[o].r==r) return tree[o].minn;
     77     int mid=(tree[o].l + tree[o].r)/2,why;
     78     if (r<=mid) why=ask_min(o*2,l,r);
     79     else if(l>mid) why=ask_min(o*2+1,l,r);
     80     else why=min(ask_min(o*2,l,mid),ask_min(o*2+1,mid+1,r));
     81     return why;
     82 }
     83 int main()
     84 {
     85     scanf("%d%d",&n,&m);
     86     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
     87     for (int i=1;i<=m;i++)
     88     {
     89         scanf("%d%d",&l[i],&r[i]);
     90         sub[l[i]].push_back(i);
     91         add[r[i]].push_back(i);
     92     }
     93     build(1,1,n);
     94     int sum=-1,pid,tot=0;
     95     for (int i=1;i<=n;i++)
     96     {
     97         for (int j=0;j<add[i-1].size();j++)
     98         {
     99             int id=add[i-1][j];
    100             up(1,l[id],r[id],1);
    101         }
    102         for (int j=0;j<sub[i].size();j++)
    103         {
    104             int id=sub[i][j];
    105             up(1,l[id],r[id],-1);
    106         }
    107         int why=ask_max(1,1,n)-ask_min(1,1,n);
    108         if (why>=sum)
    109         {
    110             sum=why;
    111             pid=i;
    112         }
    113     }
    114     printf("%d
    ",sum);
    115     for(int i=1;i<=m;i++) 
    116         if(l[i]<=pid && pid<=r[i]) ans[++tot]=i;
    117     printf("%d
    ",tot);
    118     for(int i=1;i<=tot;i++) printf("%d ",ans[i]); 
    119     return 0;
    120 }
    View Code

    F. MST Unification

    题意:给你一个2e5个点,2e5条边的无向图,保证没有自环,2个点之间也只有1条边,你可以选择其中的一些边,让他们的权值+1或者翻倍,

             问你最少改几条边,使得这个图的最小生成树是唯一的

    题解:我们回想kruskal的过程,我们把边排序后,从小开始选择,如果这条边的2个端点没联通,那么我们会考虑选择他,

            为什么我们说会考虑,因为我们一般只求最小生成树的大小,而不去在意他的长相,但在这里,我们显然可以想到,

            同样相同的权值的几条边,我们会优先选择哪一条呢?

            每一次我们先找到权值相同的那些边,然后开始选择,首先我们看他们2个端点是否已经联通,这样的边一定不会选,所以也一定不用改

            我们再扫一次,这一次看哪些边需要联通,且边同时就把他们联通了,选中的边就是选定成为生成树里的边,而此时那些还联通着的边且拥有相同权值的边,就应该改变

            有人会问,难道不可能是几条边的和一样吗,(1+2+5=2+2+4)类似的情况吗,我们还是回到kruskal,最小的一定会选的!而且2点之间也只有1条边,

           所以造成最小生成树不唯一的情况只会是有相同权值的边,同时可以被选择,选择一个后另一个就没用了这种情况

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200006
     4 int n,m,fa[N],ans;
     5 struct rec
     6 {
     7     int x,y,z;
     8     bool operator <(const rec w) const {return z < w.z;}
     9 }a[N];
    10 int get(int x) 
    11 {
    12     if (x==fa[x]) return x;
    13     return fa[x]=get(fa[x]);
    14 }
    15 int main() 
    16 {
    17     scanf("%d%d",&n,&m);
    18     for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    19     sort(a+1,a+m+1);
    20     for (int i=1;i<=n;i++) fa[i]=i;
    21     for (int i=1,j=1;i<=m;i=j) 
    22     {
    23         while (j<=m && a[j].z==a[i].z) j++;
    24         int cnt=j-i;
    25         for (int t=i;t<j;t++) 
    26     {
    27             int x=get(a[t].x),y=get(a[t].y);
    28             if (x==y) cnt--;
    29         }
    30         for (int t=i;t<j;t++) 
    31     {
    32             int x=get(a[t].x),y=get(a[t].y);
    33             if (x!=y) 
    34             {
    35         cnt--;
    36                 fa[x]=y;
    37             }
    38         }
    39         ans+=cnt;
    40     }
    41     printf("%d",ans);
    42     return 0;
    43 }
    View Code
  • 相关阅读:
    013.ES6 -对象字面量增强型写法
    012. ES6
    011. ES6 语法
    10. 9. Vue 计算属性的setter和getter 以及 计算属性的缓存讲解
    4. Spring MVC 数据响应方式
    3. SpringMVC 组件解析
    9. Vue 计算属性
    【洛谷 2984】给巧克力
    【洛谷 1821】捉迷藏 Hide and Seek
    【洛谷 1821】银牛派对Silver Cow Party
  • 原文地址:https://www.cnblogs.com/qywhy/p/10332392.html
Copyright © 2011-2022 走看看