[题解] AtCoder Beginner Contest 409(ABC409) A~F

A - Conflict

输出Yes\(\iff\)存在\(t[i]\)\(a[i]\)同时为o

时间复杂度\(O(1)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
string t,a;
bool check(){
	for(int i=0;i<n;i++) if(t[i]=='o'&&a[i]=='o') return 1;
	return 0;
}
signed main(){
	cin>>n>>t>>a;
	cout<<(check()?"Yes\n":"No\n");
	return 0;
}

B - Citation

显然答案\(\in[0,n]\),枚举验证即可。时间复杂度\(O(n^2)\)

点击查看代码
#include<bits/stdc++.h>
#define N 105
using namespace std;
int n,a[N];
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=n;~i;i--){
		int cnt=0;
		for(int j=1;j<=n;j++){
			cnt+=(a[j]>=i);
		}
		if(cnt>=i) cout<<i,exit(0);
	}
	return 0;
}

发现答案有单调性,也可以二分做到\(O(n\log n)\)

C - Equilateral Triangle

首先\(L\bmod 3\neq 0\)的话直接输出No

然后用一个桶数组记录下每个位置的点数量,然后遍历形如\((i,i+\frac{L}{3},i+\frac{2L}{3})\)的三元组统计答案即可。

时间复杂度\(O(n+L)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 300010
using namespace std;
int n,l,d,cur,t[N],ans;
signed main(){
	cin>>n>>l,t[0]=1;
	for(int i=1;i<n;i++) cin>>d,(cur+=d)%=l,t[cur]++;
	if(l%3) cout<<0,exit(0);
	for(int i=0;i<l/3;i++)
		ans+=t[i]*t[i+l/3]*t[i+l/3*2];
	cout<<ans<<"\n";
	return 0;
}

D - String Rotation

显然可以贪心。找到最小的\(i\)使得\(s[i]>s[i+1]\),然后将\(s[i]\)取出,放在最小的\(j\)使得\(s[j]>s[i]\)之前。

若找不到这样的\(j\)就把\(s[i]\)放在最后面;若找不到这样的\(i\)则直接原样输出。

时间复杂度\(O(n)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n;
string s;
signed main(){
	cin>>t;
	while(t--){
		cin>>n>>s;
		bool f=0;
		for(int i=0;i<n-1;i++){
			if(s[i]>s[i+1]){
				for(int j=0;j<i;j++) cout<<s[j];
				bool flg=0;
				for(int j=i+1;j<n;j++){
					if(!flg&&s[j]>s[i]) flg=1,cout<<s[i];
					cout<<s[j];
				}
				if(!flg) cout<<s[i];
				cout<<"\n";
				f=1;
				break;
			}
		}
		if(!f) cout<<s<<"\n";
	}
	return 0;
}

E - Pair Annihilation

单独考虑一条边对答案的贡献,任何一条边\((u,v,w)\)连接的\(2\)个部分的总和\(S\)\(S'\)一定互为相反数,对答案至少有\(|S|*w\)的贡献。

因此只要电荷的移动不走回头路,就不存在冗余操作,答案就是最优的。

我们可以从叶节点开始逐层向上转移,转移的途中统计答案,到根节点就算结束,类似拓扑排序。

时间复杂度\(O(n)\)

点击查看代码
#include<bits/stdc++.h>
#define N 100010
#define int long long
using namespace std;
int n,x[N],deg[N],ans;
struct edge{int to,w;};
vector<edge> G[N];
queue<int> q;
void add(int u,int v,int w){G[u].emplace_back(edge{v,w}),deg[u]++;}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>x[i];
	for(int i=1,u,v,w;i<n;i++) cin>>u>>v>>w,add(u,v,w),add(v,u,w);
	for(int i=1;i<=n;i++) if(deg[i]==1) q.push(i);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto i:G[u]){
			int v=i.to,w=i.w;
			if(!deg[v]) continue;
			deg[u]--,deg[v]--;
			ans+=abs(x[u])*w,x[v]+=x[u];
			if(deg[v]==1) q.push(v);
		}
	}
	cout<<ans<<"\n";
	return 0;
}

F - Connecting Points

用并查集来维护连通性,并使用优先队列来选择距离最小的点对。

  • 对于操作\(1\),遍历之前所有的点\(v\),把它们和新点\(u\)的距离\(d\)\((u,v,d)\)的形式扔进优先队列。
  • 对于操作\(2\),从队列中取出第一个\((u,v,d)\)使得\(u,v\)不在同一个连通块中。
    • 若找不到,则输出-1
    • 若能找到,则继续在队列中找所有\((u',v',d)\),将\(u'\)\(v'\)在并查集上合并。
  • 对于操作\(3\),看看\(u,v\)是否处于并查集的同一集合中即可。

时间复杂度\(O((n+q)^2\log (n+q)^2)=O((n+q)^2\log (n+q))\)

点击查看代码
#include<bits/stdc++.h>
#define N 1505
#define Q 1505
#define int long long
using namespace std;
struct Node{
	int d,u,v;
	bool operator < (const Node&x) const{return x.d<d;}
};
priority_queue<Node> q;
int n,tq,x[N+Q],y[N+Q],idx,fa[N+Q];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int dis(int i,int j){return abs(x[i]-x[j])+abs(y[i]-y[j]);}
void ins(int _x,int _y){
	x[++idx]=_x,y[idx]=_y,fa[idx]=idx;
	for(int i=1;i<idx;i++) q.push({dis(i,idx),i,idx});
}
signed main(){
	cin>>n>>tq;
	for(int i=1,x,y;i<=n;i++) cin>>x>>y,ins(x,y);
	while(tq--){
		int op,a,b;
		cin>>op;
		if(op==1){
			cin>>a>>b;
			ins(a,b);
		}else if(op==2){
			int k=-1;
			while(!q.empty()){
				Node t=q.top();
				if((~k)&&k!=t.d) break;
				q.pop();
				if(find(t.u)==find(t.v)) continue;
				if(k==-1) k=t.d;
				if(k!=t.d) continue;
				else fa[find(t.u)]=find(t.v);
			}
			cout<<k<<"\n";
		}else{
			cin>>a>>b;
			cout<<(find(a)==find(b)?"Yes\n":"No\n");
		}
	}
	return 0;
}
posted @ 2025-06-07 23:17  Sinktank  阅读(356)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.