Codeforces Round 947 (Div. 1 + Div. 2)
发现今天做不了一点题,遂来补以前的比赛。
B. 378QAQ and Mocha's Array
秒了。排序,取最小的数记为 ,再取 最小的无法被 整除的数记为 ,如果仍然存在无法被 整除的数,则无解。
C. Chamo and Mocha's Array
容易想到一个结论:如果一个数比它左边或右边的数小,那么它可以成为答案。但这样是不对的,样例:3 1 4 1 5。
正确结论:如果一个数向左右扩展两格后有比它大的数,那么它可以成为答案。
D. Paint the Tree
首先我们找到 点间靠近 的中点,以这个点作为根 ,然后答案就是 , 是 到 的距离, 是以 为根时的最大深度。
实际上很简单,只不过我赛时降智,一直在想走重儿子而不走最深的儿子,还坑了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;
}//我服了爸爸
頑張って