Codeforces Round 541 (Div. 2)
layout: post
title: Codeforces Round 541 (Div. 2)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces
- 並查集
---
傳送門
A.Sea Battle (簽到)
題意
給你一個上下兩個矩形,讓他們左邊對著拼起來,求出他們外面一圈的面積
思路
關鍵就是中間那一塊留面積大的就行
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1e6+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); ll a,b,c,d; cin>>a>>b>>c>>d; ll ans=0; ans+=(a+2)*(b+1); ans+=(c+2)*(d+1); ans-=min(a+2,c+2); ans+=max(a+2,c+2); ans-=a*b+c*d; cout<<ans; return 0; }
B.Draw! (模擬)
題意
按順序給你一堆比分,問你最多能出現幾場勝場
思路
也是直接模擬,不過要註意平局的時候
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=2e5+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); ll ans=1; int n; cin>>n; ll aa=0,bb=0; for(int i=1;i<=n;i++){ ll a,b; cin>>a>>b; if(a<bb||b<aa){ aa=a,bb=b;continue; } ans+=min(a,b)-max(aa,bb)+1; if(aa==bb)ans--; aa=a,bb=b; } cout<<ans; return 0; }
C.Birthday (模擬)
題意
給你一堆高度,讓你重新排成一個圓使得對於任意一個高度她周圍的差盡可能小
思路
對於一個數,那麽她周圍的肯定是和他最近的數,所以直接排序一下,拿一個雙端隊列前後模擬一下就行
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1e6+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int a[maxn]; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } sort(a+1,a+1+n); deque<int>dq; for(int i=1;i<=n;i++){ if(i&1) dq.push_back(a[i]); else dq.push_front(a[i]); } for(int i=1;i<=n;i++){ cout<<dq.front()<<" "; dq.pop_front(); } return 0; }
D.Gourmet choice (並查集縮點+拓撲排序)
題意
有N+M個數 給出他們之間兩兩的比較,讓你構造出一組數據滿足這個比較
思路
首先考慮‘=‘如果有=的話說明他們的值是一樣的 所以可以把他們縮成一個點,可以減少計算量
然後對於‘>‘和"<"其實我們都可以轉化成‘>‘ 對於一個>我們可以變成一個圖,表示>右邊的那個數比左邊的小,連小一條線,說明左邊的要等右邊的數字都分配完再分配
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m;
int fa[maxn],d[maxn],a[maxn];
vector<int>G[maxn];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
char s[2005][2005];
void add(int i,int j){
int aa=find(i),bb=find(j);
if(aa==bb)puts("No"),exit(0);
d[aa]++;
G[bb].push_back(aa);
}
int vis[maxn];
void topo(){
queue<pair<int,int> >Q;
for(int i=1;i<=n+m;i++){
int aa=find(i);
if(!d[aa]&&!vis[aa])Q.push(make_pair(aa,1)),vis[aa]=1;
}
while(!Q.empty()){
pair<int,int> now=Q.front();Q.pop();
int u=now.first;
a[u]=max(a[u],now.second);
for(auto i:G[u]){
a[i]=max(a[u]+1,a[i]);
d[i]--;
if(!d[i])Q.push(make_pair(i,a[i]));
}
}
for(int i=1;i<=n+m;i++)
if(d[i])puts("No"),exit(0);
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n+m;i++)fa[i]=i;
for(int i=1;i<=n;i++){
cin>>s[i]+1;
for(int j=1;j<=m;j++){
if(s[i][j]=='='){
int aa=find(i),bb=find(j+n);
fa[bb]=aa;
}
/* else if(s[j]=='>'){
add(i,j+n);
}
else add(n+j,i);*/
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(s[i][j]=='>')add(i,n+j);
if(s[i][j]=='<')add(n+j,i);
}
topo();
cout<<"Yes"<<endl;
for(int i=1;i<=n;i++)cout<<a[find(i)]<<" ";cout<<endl;
for(int j=1;j<=m;j++)cout<<a[find(j+n)]<<" ";
return 0;
}
/*
3 3
<<<
<<=
<<=
*/
E.String Multiplication(DP)
題意
定義一種字符串乘法 如果aab*c變成cacacbc
就是用後一個字符串填滿前一個字符串的空隙和前後
問你n個乘法過後的結果字符串的最長連續相同字母是多少
思路
可以發現答案又最後一種字符串控制,因為就算前面的答案是多少都會被最後一個字符串拆開
所以分析最後一個字符串,發現情況有三種
如果最後一個字符串字符只有一種,那麽答案就為這個前面那個字符串的這個字符長度+1 並且乘上最後一個字符串的長度 + 前面那個字符串的長度
如果是 不是的話那麽答案就只和最後字符串的前後字符有關系,答案就是當前字符串的前後最長長度+(前面的答案是否有包含這個字符) 如果前後的字符都一樣的話那麽答案又不同了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int dp[maxn][26],a[26],head,tail,ans;
char s[maxn];
void init(){
memset(a,0,sizeof(a));
int n=strlen(s+1),t=1;
for(int i=2;i<=n;i++){
if(s[i]!=s[i-1])
a[s[i-1]-'a']=max(a[s[i-1]-'a'],t),t=1;
else t++;
}
a[s[n]-'a']=max(a[s[n]-'a'],t);
head=tail=1;
for(int i=2;i<=n;i++)
if(s[i]==s[i-1])head++;
else break;
for(int i=n-1;i>=1;i--)
if(s[i]==s[i+1])tail++;
else break;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s+1;
int len=strlen(s+1);
init();
if(head==len){
int k=s[1]-'a';
dp[i][k]=head*(dp[i-1][k]+1)+dp[i-1][k];
}
for(int j=0;j<26;j++){
dp[i][j]=max(dp[i][j],a[j]);
if(dp[i-1][j]){
dp[i][j]=max(dp[i][j],1);
int p1=0,p2=0;
if(s[1]==char('a'+j)){
p1=1;
dp[i][j]=max(dp[i][j],head+1);
}
if(s[len]==char('a'+j)){
p2=1;
dp[i][j]=max(dp[i][j],tail+1);
}
if(p1&&p2)dp[i][j]=max(dp[i][j],head+tail+1);
}
if(i==n)ans=max(ans,dp[i][j]);
}
}
cout<<ans;
return 0;
}
F.Asya And Kittens (啟發式合並 or ripe黑科技 or 鏈表操作)
題意
給你n-1對,相鄰的在一塊,選了這兩個數,這兩個集合就可以看成一個集合了,問符合條件的序列。
思路
很容易想到並查集的合並操作,對於一次合並相當於把兩個集合變成了一塊,那麽現在的問題就是怎麽處理集合合並
方法有三,
1.啟發式合並,每次把容量小的合並到容量大的裏面去,這樣可以保證復雜度是log
2.鏈表,這樣直接把頭指針插到另一個的尾指針上,每一個的操作復雜度為o(1)
3.rope 黑科技,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=2e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int fa[maxn];
vector<int>G[maxn];
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
fa[i]=i;G[i].push_back(i);
}
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
int fx=fa[x],fy=fa[y];
if(G[fx].size()<G[fy].size())swap(fx,fy);
for(int j=0;j<G[fy].size();j++){
G[fx].push_back(G[fy][j]);
fa[G[fy][j]]=fx;
}
G[fy].clear();
}
for(int i=0;i<n;i++){
cout<<G[fa[1]][i]<<" ";
}
return 0;
}
rope
#include<bits/stdc++.h>
#include<ext/rope>
using namespace __gnu_cxx;
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
rope<int>a[maxn];
int fa[maxn];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
a[i].push_back(i);
fa[i]=i;
}
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
x=find(x),y=find(y);
a[x]+=a[y];
fa[y]=x;
}
for(int i=1;i<=n;i++){
if(find(i)==i){
for(int j=0;j<a[i].size();j++)cout<<a[i][j]<<" ";
}
}
return 0;
}
Codeforces Round 541 (Div. 2)