Codeforces Round #656 (Div.3) 解题报告
Codeforces Round #656 (Div. 3)
原文链接 https://www.cnblogs.com/-Dominate-/p/13550490.html
A. Three Pairwise Maximums
思路
分类讨论,x、y、z三个数有两个数相等且另一个数小于等于这两个数就能找到合法的a、b、c,具体直接看代码吧。(水题练下python)
T=int(input())
for i in range(T):
x,y,z=map(int,input().split())
if x==y:
if z>x:
print("NO")
continue
else:
print("YES")
print(x,z,1)
elif x==z:
if y>x:
print("NO")
continue
else:
print("YES")
print(y,x,1)
elif y==z:
if x>y:
print("NO")
continue
else:
print("YES")
print(1,x,z)
else:print("NO")
B. Restore the Permutation by Merger
思路
简单贪心,每次碰到不同的数直接输出或者记录下来最后输出都ok。
T=int(input())
for tt in range(T):
hh=[]
vis=[0]*200
ans=[]
n=int(input())
hh=list(map(int,input().split()))
for i in hh:
if vis[i]==0:
ans.append(i)
vis[i]=1
for i in ans:
print(i,end=' ')
C. Make It Good
思路
因为只能删前缀,所以很容易想到从后往前找一个倒序先增后减序列,碰到“谷”直接记录序号退出循环输出就好了。
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int a[200050];
// inline int read()
// {
// int x=0,f=1;char ch=getchar();
// while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
// while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
// return x*f;
// }
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int f=0,ans=0;
for(int i=n-1;i>=1;i--)
{
if(!f)
{
if(a[i]<a[i+1])f=1;
}
else
{
if(a[i]>a[i+1]){ans=i;break;}
}
}
cout<<ans<<"\n";
}
return 0;
}
D. a-Good String
思路
读完题发现很明显的分治,n是2的17次方,写个递归暴力就能过。
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
char s[132000];
// inline int read()
// {
// int x=0,f=1;char ch=getchar();
// while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
// while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
// return x*f;
// }
int solve(int l,int r,char ch)
{
if(l==r)return s[l]!=ch;
int mid=l+r>>1;
int cntl=0,cntr=0;
for(int i=l;i<=mid;i++)if(s[i]!=ch)cntl++;
for(int i=mid+1;i<=r;i++)if(s[i]!=ch)cntr++;
int ans1=solve(mid+1,r,ch+1),ans2=solve(l,mid,ch+1);
return min(ans1+cntl,ans2+cntr);
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
int n;cin>>n;
cin>>s+1;
cout<<solve(1,n,'a')<<'\n';
}
return 0;
}
E. Directing Edges
思路
感觉是道好题,有向无向边需要分开处理,拓扑排序来避免环的出现也很妙。首先对所有的有向边建图判环,有环直接输出NO,无环则剩下的边可以按照拓扑序从小到大连边,拓扑序就按编号从小到大连边。根据拓扑排序的原理,一个点在访问过后不会再被访问,可以完美避免环的出现。
此处有参考suxxsfe的题解,传送门。
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+50;
int Head[maxn],V[maxn*2],Nxt[maxn*2],du[maxn],vis[maxn],crcl[maxn],step[maxn];
int tot,cnt,cntt,cnttt;
int n,m;
pair<int,int>e[maxn],ee[maxn];
void Add(int u,int v){V[++tot]=v;Nxt[tot]=Head[u];Head[u]=tot;}
int dfs(int u)
{
vis[u]=crcl[u]=1;
for(int i=Head[u];i;i=Nxt[i])
{
int v=V[i];
if(crcl[v])return 1;
if(!vis[v])
{
int tmp=dfs(v);
if(tmp)return 1;
}
}
crcl[u]=0;
return 0;
}
void topsort(){
queue<int>p,q;
int i,u,v;
for(i=1;i<=n;i++)if(!du[i])q.push(i);
while(!q.empty()){
cnt++;
while(!q.empty())
{
u=q.front();q.pop();
step[u]=cnt;
for(i=Head[u];i;i=Nxt[i])
{
v=V[i];
du[v]--;
if(!du[v])p.push(v);
}
}
swap(p,q);
}
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int type,u,v;
cin>>type>>u>>v;
if(type)
{
Add(u,v);du[v]++;
ee[++cnttt].first=u;ee[cnttt].second=v;
}
else e[++cntt].first=u,e[cntt].second=v;
}
int f=0;
for(int i=1;i<=n;i++)
if(!vis[i])
{
int tmp=dfs(i);
if(tmp){f=1;break;}
}
if(f){cout<<"NO\n";}
else
{
topsort();
cout<<"YES\n";
for(int i=1;i<=cnttt;i++)
cout<<ee[i].first<<" "<<ee[i].second<<"\n";
for(int i=1;i<=cntt;i++)
if(step[e[i].first]<step[e[i].second]||(step[e[i].first]==step[e[i].second]&&e[i].first<e[i].second))cout<<e[i].first<<" "<<e[i].second<<"\n";
else cout<<e[i].second<<" "<<e[i].first<<"\n";
}
for(int i=1;i<=n;i++)Head[i]=vis[i]=crcl[i]=du[i]=0;
tot=cnt=cntt=cnttt=0;
}
return 0;
}
F. Removing Leaves
思路
读完题思路很明确,一直贪心删叶节点就好了,但是自己实现的时候发现光用vector不太行(太菜了QAQ),后来参考了大神代码发现加上队列或者集合维护就很好写。
此处有参考 nofuck~ 大神的代码。传送门
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+50;
vector<int> g[maxn];
int du[maxn],vis[maxn],sz[maxn];
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
int n,k,ans=0;cin>>n>>k;
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
g[u].push_back(v);g[v].push_back(u);
du[u]++;du[v]++;
}
queue<int> q;
for(int i=1;i<=n;i++)
if(du[i]==1)q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();vis[u]=1;
for(auto v:g[u])
{
if(vis[v])continue;
du[v]--;sz[v]++;
if(sz[v]%k==0)ans++;
if(du[v]==1&&sz[v]%k==0)q.push(v);
}
}
cout<<ans<<"\n";
for(int i=1;i<=n;i++)
du[i]=vis[i]=sz[i]=0,g[i].clear();
}
return 0;
}
G. Columns Swaps
思路
一开始有想到类似的题,比如洛谷的关押罪犯和食物链,感觉用并查集+分身法可以解决,然后不太想写逛题解的时候发现有人提到二分图染色可以做,于是果断开始写二分图染色,然后日常写挂后%大神代码。。
核心想法就是如果一行有两个a,那么必有一个换另一个不换;如果一行只有一个a,那么这列不换另一个a的列也不换,这列换另一个a的列也要换。
此处有参考 ..vince 大神的代码。传送门
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+50;
int A[maxn],B[maxn],vis[maxn],col[maxn];
vector<int>pos[maxn];
vector<int>V[maxn];
vector<int>cols[2];
vector<int>ans;
int n,f;
void init()
{
f=0;
ans.clear();
for(int i=1;i<=n;i++)
{
vis[i]=col[i]=0;
pos[i].clear();
V[i].clear();
}
}
bool cal(int u,int v){return A[u]==A[v]||B[u]==B[v];}
void dfs(int u,int c)
{
col[u]=c;
cols[c].push_back(u);
vis[u]=1;
for(int v: V[u])
{
if(vis[v])
{
if(col[u]^cal(u,v)!=col[v])f=1;
continue;
}
dfs(v,c^cal(u,v));
}
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
init();
cin>>n;
for(int i=1;i<=n;i++)
{
int x;cin>>x;A[i]=x;
pos[x].push_back(i);
}
for(int i=1;i<=n;i++)
{
int x;cin>>x;B[i]=x;
pos[x].push_back(i);
}
int ff=0;
for(int i=1;i<=n;i++)
{
if(pos[i].size()!=2)
{
ff=1;
break;
}
if(pos[i][0]==pos[i][1])continue;
V[pos[i][0]].push_back(pos[i][1]);
V[pos[i][1]].push_back(pos[i][0]);
}
if(ff){cout<<"-1\n";continue;}
for(int i=1;i<=n;i++)
if(!vis[i])
{
cols[0].clear();cols[1].clear();
dfs(i,0);
if(cols[0].size()<cols[1].size())
for(auto x:cols[0])
ans.push_back(x);
else
for(auto x:cols[1])
ans.push_back(x);
}
if(f){cout<<"-1\n";continue;}
int len=ans.size();
cout<<len<<"\n";
for(int i=0;i<len;i++)
{
cout<<ans[i];
if(i==len-1)cout<<'\n';
else cout<<" ";
}
if(len==0)cout<<'\n';
}
return 0;
}

浙公网安备 33010602011771号