codeforces#541 1131a-----1131f

Posted pandaking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces#541 1131a-----1131f相关的知识,希望对你有一定的参考价值。

a:没啥,主要是要手速快,不过我手速显然不够快,阅读能力不行啊。。。。。。

技术图片
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 ll w1,h1,w2,h2;
 7 int main(){
 8     scanf("%lld%lld%lld%lld",&w1,&h1,&w2,&h2);
 9     printf("%lld
",(h1+h2)*2+2*(w1+2));
10     return 0;
11 }
View Code

b:同上

技术图片
 1 By Pnada_Kinggggggggggggg, contest: Codeforces Round #541 (Div. 2), problem: (B) Draw!, Accepted, #
 2  #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <bitset>
 8 using namespace std;
 9 typedef long long ll;
10 const int maxn=10100;
11 int n;
12 struct node{
13     ll xi,yi;
14 };
15 node sum[maxn];
16 int main(){
17     scanf("%d",&n);
18     sum[0].xi=0;sum[0].yi=0;
19     for(int i=1;i<=n;i++) scanf("%lld%lld",&sum[i].xi,&sum[i].yi);
20     ll ans=1;
21     for(int i=1;i<=n;i++){
22         if(sum[i-1].xi<sum[i-1].yi){
23             if(sum[i].xi>=sum[i-1].yi) ans+=min(sum[i].xi-sum[i-1].yi+1,sum[i].yi-sum[i-1].yi+1);
24         }else if(sum[i-1].xi>sum[i-1].yi){
25             if(sum[i].yi>=sum[i-1].xi) ans+=min(sum[i].xi-sum[i-1].xi+1,sum[i].yi-sum[i-1].xi+1);
26         }else{
27             ans+=min(sum[i].xi-sum[i-1].yi,sum[i].yi-sum[i-1].xi);
28         }
29     }
30     printf("%lld
",ans);
31     return 0;
32 }
View Code

c:同上

技术图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long ll;
 8 int n;
 9 ll num[130];
10 ll a[130];
11 int main(){
12     scanf("%d",&n);
13     for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
14     sort(num+1,num+n+1);
15     if(n%2==1){
16         int len=n/2+1;
17         a[len]=num[n];len--;
18         int cnt=1;
19         for(int i=len;i>=1;i--){
20             a[i]=num[n-cnt];
21             a[n-i+1]=num[n-cnt-1];
22             cnt+=2;
23         }
24     }else{
25         int len=n/2;
26         int cnt=0;
27         for(int i=len;i>=1;i--){
28             a[i]=num[n-cnt];
29             a[n-i+1]=num[n-cnt-1];
30             cnt+=2;
31         }
32     }
33     for(int i=1;i<n;i++) printf("%lld ",a[i]);
34     printf("%lld
",a[n]);
35     return 0;
36 }
View Code

d:题意:第一天有n个菜,第二天有m个菜,給一个n*m矩阵, 含有  > =  <三个字符, a(i,j)指的是:第一天的第i件菜的美味度 >  =  <第二天的第j件菜的美味度。求出满足这个矩阵的n+m件菜的各自的美味度,

要求使用的最大数字尽量小。

首先说怎么去想吧:这个很容易往图的方向去想,然后就可以想到拓扑排序。那么怎么解决相等这个问题了,这个就可以想到并查集了,数据结构的重要性啊。。。。。

启发: 1:不要用两个数组,用一个数组就可以想到图的方向   2:然后判相等可以用并查集   

然后就没啥了,接下来是代码:

技术图片
 1 #include <algorithm>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <vector>
 7 #include <bitset>
 8 #include <queue>
 9 using namespace std;
10 int n,m;
11 vector<int> G[2200];
12 char sz[1010][1010];
13 int f[2100];
14 int in[2100];
15 int ans[2100];
16 
17 int find(int x){
18     if(f[x]==x) return x;
19     else return find(f[x]);
20 }
21 
22 bool toposort(){
23     queue<int> que;
24     for(int i=1;i<=n+m;i++){
25         if(i==find(i)&&in[find(i)]==0){
26             que.push(i);ans[i]=1;
27         }
28     }
29     while(!que.empty()){
30         int u=que.front();que.pop();
31         for(int i=0;i<G[u].size();i++){
32             int v=G[u][i];
33             in[v]--;
34             if(in[v]==0){
35                 que.push(v);
36                 ans[v]=ans[u]+1;
37             }
38         }
39     }
40     for(int i=1;i<=n+m;i++) if(!ans[find(i)]) return false;
41     else return true;
42 }
43 
44 int main(){
45     scanf("%d%d",&n,&m);
46     for(int i=1;i<=n+m;i++) f[i]=i;
47     for(int i=1;i<=n;i++){
48         scanf("%s",sz[i]+1);
49         for(int j=1;j<=m;j++){
50             if(sz[i][j]===){
51                int t1=find(i),t2=find(j+n);
52                f[t1]=t2;
53             }
54         }
55     }
56     for(int i=1;i<=n;i++){
57         for(int j=1;j<=m;j++){
58             int t1=find(i),t2=find(j+n);
59             if(sz[i][j]==>){
60                 G[t2].push_back(t1);
61                 in[t1]++;
62             }
63             if(sz[i][j]==<){
64                 G[t1].push_back(t2);
65                 in[t2]++;
66             }
67         }
68     }
69     if(!toposort()) printf("No
");
70     else{
71         printf("Yes
");
72         for(int i=1;i<=n;i++) printf("%d ",ans[find(i)]);
73         printf("
");
74         for(int i=n+1;i<=n+m;i++) printf("%d ",ans[find(i)]);
75         printf("
");
76     }
77     return 0;
78 }
View Code

e:题意,定义一种字符串操作  有两个字符串s和t s*t  就会变成一个新的字符串   t+s1+t+s2+t......+sn+t;

然后给你n个字符串,求这n个字符串连续乘积的和中连续出现的字符的最大个数!

首先:这应该是一个很想的递推把,设f[i][j]为第i次操作形成的字符串中字符j出现的次数,那么考虑两种情况,便很好就可以从两种情况下手,第一种情况就是这个新的字符串都是

j这个字符和不是的这两种情况。

启发: 1:这种题目应该在草稿纸上面捋清楚思绪再写的

代码:

技术图片
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <bitset>
 7 using namespace std;
 8 const int maxn=100100;
 9 int S=26;
10 int n;
11 int dp[maxn][26];
12 int pre[26],suf[26];
13 char sz[maxn];
14 
15 void solve(int *f){
16      scanf("%s",sz+1);
17      int len=strlen(sz+1);
18      for(int i=0;i<S;i++){
19          int mx=0;
20          int now=0;
21          for(int j=1;j<=len;j++){
22              if(i==(sz[j]-a)) mx=max(mx,++now);
23              else now=0;
24          }
25          f[i]=mx;pre[i]=0,suf[i]=0;
26          for(int j=1;j<=len;j++){
27              if(i==(sz[j]-a)) pre[i]++;
28              else break;
29          }
30          for(int j=len;j>=1;j--){
31              if(i==(sz[j]-a)) suf[i]++;
32              else break;
33          }
34      }
35 }
36 
37 int main(){
38     scanf("%d",&n);
39     solve(dp[1]);
40     for(int i=2;i<=n;i++){
41         solve(dp[i]);
42         int len=strlen(sz+1);
43         for(int j=0;j<S;j++) {
44             if(dp[i-1][j]>0){
45                 if (pre[j]==len) dp[i][j] = max(dp[i][j], len * (dp[i - 1][j] + 1) + dp[i - 1][j]);
46                 else dp[i][j] = max(dp[i][j], pre[j] + suf[j] + 1);
47             }
48         }
49     }
50     int ans=0;
51     for(int i=0;i<S;i++) ans=max(ans,dp[n][i]);
52     printf("%d
",ans);
53     return 0;
54 }
View Code

f:给你n个点,每次你可以合并相邻的两个点,会给你n-1次合并机会,要你求最开始可能出现的排列情况

这个我一开始往带权并差集上面想了,结果发现不用,我只要按基础并查集的操作建一颗树就够了,是我想的太复杂了

接下来是代码:

技术图片
 1 #include <bits/stdc++.h>
 2 #define maxn 150005
 3 using namespace std;
 4 int pre[maxn];
 5 int n;
 6 vector<int> v[maxn];
 7  
 8 void init(){
 9   for(int i=0;i<=n;i++){
10     pre[i] = i;
11   }
12 }
13  
14 void dfs(int x){
15   printf("%d ", x);
16   for(int i=0;i<v[x].size();i++) dfs(v[x][i]);
17 }
18  
19 int Find(int x){
20   if(x != pre[x]){
21     pre[x] = Find(pre[x]);
22   }
23   return pre[x];
24 }
25  
26 void merge(int x,int y){
27   int fx = Find(x);
28   int fy = Find(y);
29   if(fx != fy){
30     pre[fy] = fx;
31     v[fx].push_back(fy);
32   }
33 }
34  
35 int main()
36 {
37   scanf("%d",&n);
38   init();
39   for(int i=1;i<n;i++){
40     int u, v;
41     scanf("%d%d",&u, &v);
42     merge(u, v);
43   }
44   dfs(Find(1));
45   return 0;
46 }
View Code

 

以上是关于codeforces#541 1131a-----1131f的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #541 (Div. 2) 题解

Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

Codeforces Round #541 (Div. 2) E 字符串 + 思维 + 猜性质

CF #541 D Gourmet choice

CodeForces - 1131D(Three Integers)

cf-Round541-Div2-F(并查集+静态链表)