Codeforces Round 947 (Div. 1 + Div. 2)

发现今天做不了一点题,遂来补以前的比赛。


B. 378QAQ and Mocha's Array

秒了。排序,取最小的数记为 x,再取 最小的无法被 x 整除的数记为 y,如果仍然存在无法被 y 整除的数,则无解。

C. Chamo and Mocha's Array

容易想到一个结论:如果一个数比它左边或右边的数小,那么它可以成为答案。但这样是不对的,样例:3 1 4 1 5。

正确结论:如果一个数向左右扩展两格后有比它大的数,那么它可以成为答案。

D. Paint the Tree

首先我们找到 a,b 点间靠近 a 的中点,以这个点作为根 root,然后答案就是 2(n1)+disdistdisbroot 的距离,dist 是以 root 为根时的最大深度。

实际上很简单,只不过我赛时降智,一直在想走重儿子而不走最深的儿子,还坑了xht呜呜呜。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*114514,M=1919810;
struct xx{
	ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
	e[++cnt].next=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
ll T;
ll n,m,k,x,a,b,rt;
ll siz[N],dis[N],son[N];
void dfs(ll u,ll fa){
	siz[u]=1,son[u]=0;
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(v==fa) continue;
		dis[v]=dis[u]+1;
		dfs(v,u);
		siz[u]+=siz[v];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
}
void getrt(ll u,ll tot){
	if(tot==0){
		rt=u;
		return;
	}
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(dis[v]>dis[u]) continue;
		getrt(v,tot-1);
	}
}
void solve(){
	cin>>n;
	cin>>a>>b;
	cnt=0;
	for(int i=1;i<n;++i){
		ll x,y;
		cin>>x>>y;
		add(x,y),add(y,x);
	}
	dis[a]=0,dfs(a,0);
	ll di=dis[b]-dis[a]; di=(di+1)/2;
	ll res=di,ans=0;
	getrt(b,di); //向上走di条边,取到靠a的中点
	dis[rt]=0,dfs(rt,0);
	for(int i=1;i<=n;++i) ans=max(ans,dis[i]);
	cout<<2*(n-1)-ans+res<<'\n';
	for(int i=1;i<=cnt;++i) head[i]=0;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
} 

E.


题解代码有用到一个用异或值来得到一个唯一点的编号的技巧,以前见过,但还是很巧妙。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*114514,M=1919810;
struct xx{
	ll next,to;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
	e[++cnt].next=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
ll T;
ll n,q,c[N],f[N],xht[N];
ll cnt1,cnt2,cnt3,cnt4,pos;
//父亲是白的黑点、有两个黑儿子、有三个黑儿子、总黑点数、有两个黑儿子的点(异或求得)
//原来这个点是用异或搞出来的,6 
void dfs(ll u,ll fa){
	ll tot=0;
	if(c[u]) ++cnt4;
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(v==fa) continue;
		f[v]=u,tot+=c[v];
		dfs(v,u);
	}
	if(!c[fa]&&c[u]) ++cnt1;
	if(c[u]){
		if(tot==2) ++cnt2,pos^=u;
		if(tot>2) ++cnt3;
	}
	xht[u]=tot;
}
void calc(ll u){
	c[u]^=1;
	ll fa=f[u];
	//修改u的状态 
	if(!c[u]){
		if(!c[fa]) --cnt1;
		if(xht[u]==2) --cnt2,pos^=u;
		if(xht[u]>2) --cnt3;
		--cnt4,cnt1+=xht[u];
	}
	else{
		if(!c[fa]) ++cnt1;
		if(xht[u]==2) ++cnt2,pos^=u;
		if(xht[u]>2) ++cnt3;
		++cnt4,cnt1-=xht[u];
	}
	//修改父亲的状态 
	if(c[u]){
		if(c[fa]&&xht[fa]==2) --cnt2,++cnt3,pos^=fa;
		++xht[fa];
		if(c[fa]&&xht[fa]==2) ++cnt2,pos^=fa;
	}
	else{
		if(c[fa]&&xht[fa]==2) --cnt2,pos^=fa;
		--xht[fa];
		if(c[fa]&&xht[fa]==2) ++cnt2,--cnt3,pos^=fa;
	}
}
bool check(){
	if(cnt1>1||cnt2>1||cnt3||!cnt4) return 0;
	if(cnt2&&c[f[pos]]) return 0;
	return 1;
}
void solve(){
	cin>>n>>q;
	for(int i=1;i<=n;++i) cin>>c[i],xht[i]=0;
	for(int i=1;i<n;++i){
		ll a,b;
		cin>>a>>b;
		add(a,b),add(b,a);
	}
	cnt1=cnt2=cnt3=cnt4=pos=0;
	dfs(1,0);
	while(q--){
		ll x;
		cin>>x;
		calc(x);
		if(check()) cout<<"Yes\n";
		else cout<<"No\n";
	}
	for(int i=1;i<=cnt;++i) head[i]=0;
	cnt=0;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
}//我服了爸爸 
posted @   和蜀玩  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示