codeforces Educational Round 65 ABCDF题解

昨晚刷的cf,真的是手速场啊。

 

A题。

大水题,看看字符串中第一个8后面(包括自己)是不是大于或等于11就行了。

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 int main() {
15     int T;scanf("%d",&T);
16     for(int t=1;t<=T;++t){
17         int n;scanf("%d",&n);
18         string s;cin>>s;
19         int st=-1;
20         for(int i=0;i<n;++i){
21             if(s[i]=='8'){
22                 st=i;
23                 break;
24             }
25         }
26         if(st==-1 || n-st<11) puts("NO");
27         else puts("YES");
28     }
29     return 0;
30 }
View Code

 

B题。

emm第一次打交互题,卡了挺久的。。。。。交互题的姿势题面已经给了。然后看看那6个数字可以看出来,只要给你一个数,你肯定知道是哪两个数的乘积,所以询问1,2的乘积可以确定1,2是哪两个数(顺序还未确定),再询问2,3的乘积(顺序未定)。那样就可以知道1,2,3的顺序了,4,5,6同理

  1 // Cease to struggle and you cease to live
  2 #include <iostream>
  3 #include <cmath>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <queue>
  8 #include <vector>
  9 #include <set>
 10 #include <map>
 11 #include <stack>
 12 using namespace std;
 13 typedef long long ll;
 14 int ans[10];
 15 int val[10];
 16 map<int,int> mp;
 17 map<int,int> in;
 18 int main() {
 19     int a12,a23,a45,a56;
 20     val[1]=4;  
 21     val[2]=8;
 22     val[3]=15;
 23     val[4]=16;
 24     val[5]=23;
 25     val[6]=42;
 26     in[4]=1; 
 27     in[8]=1;
 28     in[15]=1;
 29     in[16]=1;
 30     in[23]=1;
 31     in[42]=1;
 32     cout<<"? 1 2"<<endl;
 33     fflush(stdout); 
 34     cin>>a12;
 35 
 36     cout<<"? 2 3"<<endl;
 37     fflush(stdout);
 38     cin>>a23;
 39 
 40     cout<<"? 4 5"<<endl;
 41     fflush(stdout);
 42     cin>>a45;
 43 
 44     cout<<"? 5 6"<<endl;
 45     fflush(stdout);
 46     cin>>a56;
 47 
 48     int t1,t2;
 49     for(int i=1;i<=6;++i){
 50         if(a12%val[i]) continue;
 51         if(in[a12/val[i]]==0) continue; 
 52         mp[val[i]]=1;
 53         mp[a12/val[i]]=1;
 54         t1=val[i],t2=a12/val[i];
 55         break;
 56     }
 57     for(int i=1;i<=6;++i){
 58         if(a23%val[i]) continue;
 59         if(in[a23/val[i]]==0) continue;
 60         int u=a23/val[i],v=val[i];
 61         if(mp[u]==1){
 62             ans[2]=u;
 63             ans[3]=v;
 64             if(t1==u) ans[1]=t2;
 65             else ans[1]=t1;
 66         }
 67         else {
 68             ans[2]=v;
 69             ans[3]=u;
 70             if(t1==v) ans[1]=t2;
 71             else ans[1]=t1;
 72         }
 73         break;
 74     }
 75     for(int i=1;i<=6;++i) mp[val[i]]=0;
 76 
 77     for(int i=1;i<=6;++i){
 78         if(a45%val[i]) continue;
 79         if(in[a45/val[i]]==0) continue;
 80         mp[val[i]]=1;
 81         mp[a45/val[i]]=1;
 82         t1=val[i],t2=a45/val[i];
 83         break;
 84     }
 85     for(int i=1;i<=6;++i){
 86         if(a56%val[i]) continue;
 87         if(in[a56/val[i]]==0) continue;
 88         int u=a56/val[i],v=val[i];
 89         if(mp[u]==1){
 90             ans[5]=u;
 91             ans[6]=v;
 92             if(t1==u) ans[4]=t2;
 93             else ans[4]=t1;
 94         }
 95         else {
 96             ans[5]=v;
 97             ans[6]=u;
 98             if(t1==v) ans[4]=t2;
 99             else ans[4]=t1;
100         }
101         break;
102     }
103 
104 
105     cout<<"! ";
106     fflush(stdout);
107     for(int i=1;i<6;++i){
108         cout<<ans[i]<<" ";
109         fflush(stdout);
110     }
111     cout<<ans[6]<<endl;
112     fflush(stdout);
113     return 0;
114 }
View Code

 

C题。

就是并查集的裸题,求这个集合的大小

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 const int N=5e5+9;
15 int siz[N],f[N];
16 int tem[N];
17 int find(int x){
18     if(f[x]==x) return x;
19     return f[x]=find(f[x]);
20 }
21 int main() {
22     int n,m;scanf("%d%d",&n,&m);
23     for(int i=1;i<=n;++i) f[i]=i,siz[i]=1;
24     for(int i=1;i<=m;++i){
25         int t;scanf("%d",&t);
26         for(int j=1;j<=t;++j) scanf("%d",&tem[j]);
27         sort(tem+1,tem+1+t);
28         int fa=tem[1];
29         for(int j=2;j<=t;++j){
30             int u=find(fa),v=find(tem[j]);
31             if(u!=v){
32                 f[v]=u;
33                 siz[u]+=siz[v];
34             }
35         }
36     }
37     for(int i=1;i<=n;++i){
38         int u=find(i);
39         printf("%d ",siz[u]);
40     }
41     return 0;
42 }
View Code

 

D题。

就是一个贪心题。因为我要让两者的最大值最小,那么就是不可以搞极端。从左到右枚举,记录红色和蓝色现有的“(“。出现“("时,肯定是把它往现有"("少的的那一方方。如果是出现")",那肯定是先把它往"("多的那一放。

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 int main() {
15     int n;
16     scanf("%d",&n);
17     string s;
18     cin>>s;
19     int a=0,b=0;
20     for(int i=0;i<n;++i){
21         if(s[i]=='('){
22             if(a>b){
23                 printf("0");
24                 ++b;
25             }
26             else {
27                 printf("1");
28                 ++a;
29             }
30         }
31         else{
32             if(a>b){
33                 printf("1");
34                 --a;
35             }
36             else{
37                 printf("0");
38                 --b;
39             }
40         }
41     }
42     return 0;
43 }
View Code

 

F题。

F这种就是让你求1<=l<=r<=n的l到r区间某某和的这种题,都是一个套路。1、我要做的不是枚举l和r(n²妥妥的T),我要做的是求每一个数的贡献。2、每一个数的贡献虽然看上去是和l和r有关,但是最后推出来的式子是和l和r无关的。

好,我们来看看这题。我们来看a[i]对答案的贡献,就是如果我一个l到r的区间里面,有num个比a[i]少的数,那么答案就加a[i]*num,也就是说一个比a[i]小的数都会增加a[i]对答案的贡献。那么假如在i的左边有一个a[j]<a[i],那么这个a[j]会使得a[i]对答案的贡献增多几个a[i]呢?答案是j*(n-i+1),因为有这么多个lr区间包含j和i。那么怎么统计呢?我们从左往右枚举,枚举到a[i],处理i左边的数对a[i]的对答案的贡献。那么也就是求∑j*(n-i+1)*a[i] (其中j<i,a[j]<a[i])。这个东西就用树状数组维护,注意a[i]1e9,所以要离散化。

然后再从右往左枚举,求出a[i]右边的数增加的 a[i]的对答案的贡献。

最后注意取模。乘法和取模优先级相同,原则上乘一次再模一次(因为这个WA35了。。。)

 1 // Cease to struggle and you cease to live
 2 #include <iostream>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <vector>
 9 #include <set>
10 #include <map>
11 #include <stack>
12 using namespace std;
13 typedef long long ll;
14 const ll modd=1e9+7;
15 const int N=5e5+7;
16 int n;
17 ll a[N];
18 ll b[N];
19 ll tr[N];
20 void add(int x,ll v){
21     for(;x<=n;x+=x&-x) tr[x]=(tr[x]+v)%modd;
22 }
23 ll sum(int x){
24     ll res=0;
25     for(;x;x-=x&-x) res=(res+tr[x])%modd;
26     return res;
27 }
28 int main() {
29     scanf("%d",&n);
30     ll ans=0;
31     for(int i=1;i<=n;++i) scanf("%lld",&a[i]),b[i]=a[i];
32     sort(b+1,b+1+n);
33     for(int i=1;i<=n;++i){
34         ans=(ans+a[i]*(((ll)i*(ll)(n-i+1))%modd))%modd;
35         int p=lower_bound(b+1,b+1+n,a[i])-b;
36         ans=(ans+a[i]*(sum(p-1)*(n-i+1)%modd))%modd;
37         add(p,i);
38     } 
39     memset(tr,0,sizeof(tr));
40     for(int i=n;i>=1;--i){
41         int p=lower_bound(b+1,b+1+n,a[i])-b;
42         ans=(ans+a[i]*(sum(p-1)*i%modd))%modd;
43         add(p,n-i+1);
44     }
45     printf("%lld",ans%modd);
46     return 0;
47 }
View Code

感觉这几题除了B题,代码量都很少。

posted @ 2019-05-16 22:24  小布鞋  阅读(231)  评论(0编辑  收藏  举报