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
  • 相关阅读:
    office文件在线预览,模仿网易邮箱在线预览的
    SQLServer加入域后无法远程连接
    c#将金额转换为大写,支持小数点,原创经典
    GridView多行标题行、改造标题行、自定义标题行完美版
    汇编语言常用指令
    Nature重磅:Hinton、LeCun、Bengio三巨头权威科普深度学习
    微软新技术证明深度学习还能更“深入”
    几个激光的驱动
    rplidar跑cartographer
    Git常用命令速查表
  • 原文地址:https://www.cnblogs.com/qywhy/p/10332392.html
Copyright © 2011-2022 走看看