codeforces Round #541 (Div 2)

A Sea Battle

平移过后即外围的$(w_{2} + 2) \times  (h_{1} + h_{2} + 2)$的矩形周长;

1 #include<bits/stdc++.h>
2 using namespace std;
3 int main(){
4     int w1,w2,h1,h2;
5     cin>>w1>>h1>>w2>>h2;
6     int a=w1+2,b=h1+h2+2;
7     cout<<((a+b)<<1)-4<<endl;
8     return 0;
9 }

B Draw!

为了方便设初始比分为$(-1,-1)$,假设上一次的比分为$(x_{0},y_{0})$,这次比分为$(x_{1},y_{1})$

若:1.$max(x_{0} , y_{0}) > min(x_{1} , y_{1}) $ 此时变化中一定不会出现相同的情况;

2.$max(x_{0} , y_{0}) <= min(x_{1} , y_{1})$最优的情况是将$x_{0},y_{0}$都先变成较大值,再一起增加,最后再单个增加;

注意对$x==y$的一点点特判;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,a,b,la,lb;
 4 int main(){
 5     scanf("%d",&n);
 6     la=lb=-1;
 7     long long ans=0;
 8     for(int i=1;i<=n;++i){
 9         scanf("%d%d",&a,&b);
10         ans+=max(min(a,b)-max(la,lb)+(la!=lb),0);
11         la=a,lb=b;
12     }
13     cout<<ans<<endl;
14     return 0;
15 }

C Birthday

做法好像还挺多,我不会证明,所以虽然过了也不知对不对,如果评论区有大佬路过的话欢迎评论;

比较麻烦的是两端怎么处理;

排序之后左半边奇数位顺序排列,然后再接偶数位的逆序排列;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=110;
 4 int n,a[N];
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
 8     sort(a+1,a+n+1);
 9     for(int i=1;i<=n;i+=2)printf("%d ",a[i]);
10     if(n&1)n--;for(int i=n;i;i-=2)printf("%d ",a[i]);
11     return 0;
12 }

D Gourmet choice

相当于只有‘>‘,‘=‘,对等于符号用并查集缩点;

对x>y建边:x->y;

对于得到DAG,记录一个点出发的最长链,即为答案;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2010;
 4 int n,m,f[N],mx[N],o=1,hd[N],vis[N];
 5 char s[N][N];
 6 struct Edge{int v,nt;}E[N*N];
 7 void adde(int u,int v){E[o]=(Edge){v,hd[u]};hd[u]=o++;}
 8 bool dfs(int u){
 9     mx[u]=vis[u]=1;
10     for(int i=hd[u];i;i=E[i].nt){
11         int v=E[i].v;
12         if(vis[v]==1)return false;
13         if(!vis[v]){if(!dfs(v))return false;}
14         mx[u]=max(mx[u],mx[v]+1);
15     }
16     vis[u]=2;
17     return true;
18 }
19 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
20 int main(){
21     #ifndef ONLINE_JUDGE
22     freopen("D.in","r",stdin);
23     freopen("D.out","w",stdout);
24     #endif
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n+m;++i)f[i]=i;
27     for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
28     for(int i=1;i<=n;++i)
29     for(int j=1;j<=m;++j)if(s[i][j]==‘=‘)f[find(i)]=find(j+n);
30     for(int i=1;i<=n;++i)
31     for(int j=1;j<=m;++j)
32     if(s[i][j]==‘>‘)adde(find(i),find(j+n));
33     else if(s[i][j]==‘<‘)adde(find(j+n),find(i));
34     for(int i=1;i<=n+m;++i)if(find(i)==i&&!vis[i]){
35         if(!dfs(i)){puts("NO");return 0;}
36     }
37     puts("YES");
38     for(int i=1;i<=n;++i)printf("%d ",mx[find(i)]);
39     printf("\n");
40     for(int i=1;i<=m;++i)printf("%d ",mx[find(i+n)]);
41     printf("\n");
42     return 0;
43 }

E String Multiplication

考虑每一个字符,分情况模拟即可:
对于$a+b$,

如果$b$是一个全为$x$的串,仅会连接原来的字符$x$,其余置1;

如果$b$是一个首末连续段不相接但是都为$x$的段,修改$x$,其余置1;

如果$b$是一个首末连续段不相接为$x,y(x!=y)$的段,修改$x,y$,其余置1;

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100010;
 4 int n,len,a[26],b[26],lt,p1,p2;
 5 char s[N];
 6 inline void upd(int&x,int y){if(x<y)x=y;}
 7 void cal(){
 8     len=strlen(s+1);
 9     p1=1;while(p1<len&&s[1]==s[p1+1])p1++;
10     p2=1;while(p2<len&&s[len]==s[len-p2])p2++;
11     for(int i=1,cnt=1;i<len;++i)if(s[i]!=s[i+1]){
12         upd(a[s[i]-‘a‘], cnt);
13         cnt=1;
14     }else cnt++;
15     upd(a[s[len]-‘a‘], p2);
16 }
17 int main(){
18     #ifndef ONLINE_JUDGE
19     freopen("E.in","r",stdin);
20     freopen("E.out","w",stdout);
21     #endif
22     scanf("%d",&n);
23     scanf("%s",s+1);cal();
24     for(int i=0;i<26;++i)b[i]=a[i],a[i]=0;
25     for(int i=1;i<n;++i){
26         scanf("%s",s+1);cal();
27         if(p1==len){
28             int x=s[1]-‘a‘;
29             b[x]=a[x]*b[x]+a[x]+b[x];
30             for(int j=0;j<26;++j)if(j!=x)b[j]=b[j]?1:0;
31         }else if(s[1]==s[len]){
32             int x=s[1]-‘a‘;
33             if(b[x])b[x]=p1+p2+1;
34             for(int j=0;j<26;++j)if(j!=x)b[j]=b[j]?1:0;
35         }else{
36             int x=s[1]-‘a‘,y=s[len]-‘a‘;
37             if(b[x])b[x]=p1+1;
38             if(b[y])b[y]=p2+1;
39             for(int j=0;j<26;++j)if(j!=x&&j!=y)b[j]=b[j]?1:0;
40         }
41         for(int j=0;j<26;++j)upd(b[j],a[j]),a[j]=0;
42     }
43     int ans=0;
44     for(int i=0;i<26;++i)upd(ans, b[i]);
45     cout<<ans<<endl;
46     return 0;
47 }

F Asya And Kittens

用并查集模拟,同时维护两边的位置即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=150100;
 4 int n,d[N],pre[N],nxt[N],f[N];
 5 vector<int>g[N];
 6 void adde(int u,int v){
 7     g[u].push_back(v);
 8     g[v].push_back(u);
 9     d[u]++;
10     d[v]++;
11 }
12 void dfs(int u,int fa){
13     printf("%d ",u);
14     for(int i=0;i<(int)g[u].size();++i){
15         if(g[u][i]!=fa)dfs(g[u][i],u);
16     }
17 }
18 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
19 int main(){
20     scanf("%d",&n);
21     for(int i=1;i<=n;++i)pre[i]=nxt[i]=f[i]=i;
22     for(int i=1;i<n;++i){
23         int x,y;
24         scanf("%d%d",&x,&y);
25         x=find(x),y=find(y);
26         adde(nxt[x],pre[y]);
27         nxt[x]=nxt[y];
28         f[y]=x;
29     }
30     int rt=0;
31     for(int i=1;i<=n;++i)if(d[i]==1){rt=i;break;}
32     dfs(rt,0);
33     return 0;
34 }

G

还没有改完。。。

原文地址:https://www.cnblogs.com/Paul-Guderian/p/10425270.html

时间: 2024-10-09 08:57:23

codeforces Round #541 (Div 2)的相关文章

Codeforces Round #541 (Div. 2) 题解

Codeforces Round #541 (Div. 2) 题目链接:https://codeforces.com/contest/1131 A. Sea Battle 题意: 给出两个矩形的宽和高,满足第一个矩形的左上顶点为(0,0),右下顶点为(w1,-h1):第二个矩形的坐下顶点为(0,0),右上顶点为(w2,h2).然后求围绕这两个矩形一圈的格子个数为多少. 题解: 利用二维前缀和的思路推导一下公式就行了,公式也有很多吧==我当时就是大概模拟了一下.. 代码如下: #include <

Codeforces Round #541 (Div. 2) (A~F)

目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路) F.Asya And Kittens(链表) G.Most Dangerous Shark Codeforces 1131 比赛链接 hack一个暴力失败了两次最后还是没成功身败名裂= = CF跑的也太快了吧... 不过倒也涨了不少. A.Sea Battle //想麻烦了,但是无所谓... #

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

https://codeforces.com/contest/1131/problem/D 题意 给你n个字符串,字符串长度总和加起来不会超过1e5,定义字符串相乘为\(s*s1=s1+s[0]+s1+s[1]+s1+...+s1+s[size-1]+s1+s[size]+s1\),求n个字符串依次相乘后最长连续字符相同的子序列长度 题解 鬼畜的题意 or 难以优化的复杂度,都需要观察性质才能做,第二串要插入第一个串每个字符之间,可以看出字符数增长的速度很快,所以并不能把整个字符存下来 只看一种

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

https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[],使得两个数组中最大的数尽量小 题解 按照偏序表,构造出从小到大的拓扑图 如何解决相等的数的偏序关系? 用并查集缩点后再进行拓扑排序 如何解决最大的数最小? 只需要使得同一层的数相同就行,可以一批处理栈中的元素,对于一批栈中的元素产生的新点,先放进一个容器里,然后等到这批栈清空了,再把这个容器中的点

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除