NOIP模拟<反思>(33~35)
NOIP2023模拟12联测33#
构造#
手摸你就会发现
点击查看代码
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
using namespace std;
char s[100];
char ans[100][100];
int main(){
freopen("ryx.in","r",stdin);
freopen("ryx.out","w",stdout);
int n;
scanf("%d",&n);
if(n<=20){
if(n==0){
cout<<1<<" "<<3<<endl;
for(int i=1;i<=3;i++){
cout<<"x";
}
return 0;
}
int x=n*2,y=3;
printf("%d %d\n",x,y);
for(int i=1;i<=n*2;i++){
if(i%2) printf("ryx\n");
else printf("xxx\n");
}
return 0;
}
s[1]='r';
int tot=1;
for(int i=1;i<=9;i++){
s[++tot]='y';s[++tot]='x';
s[++tot]='y';s[++tot]='r';
}
s[++tot]='y';s[++tot]='x';
if(n<=100){
int x=40,y=39;
printf("%d %d\n",x,y);
for(int i=1;i<=x;i++){
for(int j=1;j<=y;j++){
ans[i][j]='x';
}
}
int sum=n;
for(int i=1;i<=x;i++){
if(sum<=19){
i++;
for(int j=1;j<=tot;j++){
if(sum){
ans[i][j]=s[j];
if(j>=3){
if(s[j]!=s[j-1] && s[j-1]!=s[j-2] && s[j]!=s[j-2]) sum--;
}
}
}
break;
}
if(!sum){
continue;
}
if(i%2){
for(int j=1;j<=tot;j++) ans[i][j]=s[j];
sum-=19;
}
else{
continue;
}
}
for(int i=1;i<=x;i++){
for(int j=1;j<=y;j++){
cout<<ans[i][j];
}
cout<<endl;
}
return 0;
}
int sum=n;
int x=40,y=40;
cout<<x<<" "<<y<<endl;
for(int i=1;i<=x;i++){
for(int j=1;j<=y;j++){
ans[i][j]='y';
}
}
for(int i=1;i<=x;i++){
if(i==1 || i==2){
for(int j=1;j<=tot;j++) ans[i][j]=s[j];
sum-=19;
continue;
}
if(sum>=(19+38)){
for(int j=1;j<=tot;j++) ans[i][j]=s[j];
sum-=(19+38);
continue;
}
else{
if(sum){
sum--;
ans[i][1]=s[1];
}
for(int j=2;j<=tot;j++){
if(j%2==0) ans[i][j]='y';
else{
if(sum>=3){
sum-=3;
ans[i][j]=s[j];
}
else{
break;
}
}
}
break;
}
}
if(sum){
ans[1][y]=s[1],ans[2][y]=s[2];
for(int i=3;i<=x;i++){
if(!sum) break;
ans[i][y]=s[i];
if(sum){
if(s[i]!=s[i-1] && s[i]!=s[i-2] && s[i-1]!=s[i-2]){
sum--;
}
}
}
}
for(int i=1;i<=x;i++){
for(int j=1;j<=y;j++){
cout<<ans[i][j];
}
cout<<endl;
}
}
游戏#
手摸一场了考试样例没摸出来。不太擅长策略题。
从大到小排完序后,同学最优肯定是将概率分配给一个前缀,老师也是,我们可以二分一个
此时对于小于
还可以考虑因为选的是一个前缀,且概率和为 1,
化简的到
对每个前缀求出
数数#
考虑在序列上一个一个加数,使其构成单调递减的序列
首先一开始是一个长度为
点击查看代码
#include<bits/stdc++.h>
#define int long long
const int mod=998244353;
using namespace std;
const int N=100;
int f[N],n;
int l[N],r[N];
map<vector<int>,int>mp;
queue<vector<int>> q;
vector<int> s,b;
map<vector<int>,bool> vis;
signed main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++) l[i]=n+1,r[i]=0;
for(int i=1;i<=n;i++){
scanf("%lld",&f[i]);
l[f[i]]=min(l[f[i]],i),r[f[i]]=max(r[f[i]],i);
}
s.push_back(n);
mp[s]=1;
q.push(s);
vis[s]=1;
while(!q.empty()){
s=q.front();
q.pop();
vis[s]=0;
int siz=s.size();
int i=siz;
int len=0;
for(int j=0;j<siz;j++) len=max(len,s[j]);
int sum=0;
int cnt=0;
for(int j=0;j<siz;j++){
if(s[j]==len) sum++;
if(s[j]==r[i]) cnt++;
}
if(l[i]==n+1 || r[i]==0){
for(int j=0;j<siz;j++){
if((s[j]<len || sum>1) && s[j]>0){
for(int k=1;k<=s[j];k++){
b.clear();
b=s;
b.erase(b.begin()+j);
b.push_back(k-1);
b.push_back(s[j]-k);
sort(b.begin(),b.end());
if(!vis[b]){
vis[b]=1;
q.push(b);
}
mp[b]=(mp[b]+mp[s])%mod;
}
}
}
}
else{
if(len!=r[i]) continue;
for(int j=0;j<siz;j++){
for(int k=1;k<=s[j];k++){
b.clear();
b=s;
b.erase(b.begin()+j);
b.push_back(k-1);
b.push_back(s[j]-k);
sort(b.begin(),b.end());
if(b[b.size()-1]==l[i]-1){
if(!vis[b]){
vis[b]=1;
q.push(b);
}
mp[b]=(mp[b]+mp[s])%mod;
}
}
}
}
}
vector<int> ed;
ed.clear();
for(int i=1;i<=n+1;i++){
ed.push_back(0);
}
printf("%lld",mp[ed]);
}
滈葕#
首先考虑
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
const int M=1e5+10;
int head[M],ver[N*2],nex[N*2],edge[N*2],tot=0;
void add(int x,int y,int w){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot,edge[tot]=w;
}
int flatd[M],flatc[M];
struct asd{
int x,y,w;
}a[N];
int ans[M],getans=0;
bool vis[N],flat[N];
int dfs1(int x,int f){
flat[x]=1;
if(flatc[x]) return flatc[x];
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
if(flat[y]){
if(flatc[y]==1){
flatc[x]=1;
return 1;
}
continue;
}
if(dfs1(y,x)==1){
flatc[x]=1;
return 1;
}
}
flatc[x]=2;
return 0;
}
int dfs2(int x,int f){
flat[x]=1;
if(flatd[x]) return flatd[x];
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
if(flat[y]){
if(flatd[y]==1){
flatd[x]=1;
return 1;
}
continue;
}
if(dfs2(y,x)==1){
flatd[x]=1;
return 1;
}
}
flatd[x]=2;
return 0;
}
void dfs(int x,int f){
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
if(ans[y]){
if(edge[i]) if(ans[x]==ans[y]) getans=1;
if(!edge[i]) if(ans[x]!=ans[y]) getans=1;
continue;
}
if(edge[i]==1){
if(ans[x]==1) ans[y]=2;
else ans[y]=1;
}
else{
ans[y]=ans[x];
}
dfs(y,x);
}
}
int main(){
freopen("dopetobly.in","r",stdin);
freopen("dopetobly.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
if(a[i].w){
flatd[a[i].x]=1;
flatc[a[i].y]=1;
}
}
for(int i=1;i<=m;i++){
if(a[i].w==0){
vis[a[i].x]=vis[a[i].y]=1;
add(a[i].x,a[i].y,a[i].w);
}
}
for(int i=1;i<=n;i++){
if(!flatc[i]){
dfs1(i,0);
}
}
tot=0;
memset(head,0,sizeof(head));
memset(flat,0,sizeof(flat));
for(int i=1;i<=m;i++){
if(a[i].w==0){
add(a[i].y,a[i].x,a[i].w);
}
}
for(int i=1;i<=n;i++){
if(!flatd[i]){
dfs2(i,0);
}
}
for(int i=1;i<=n;i++){
if(flatd[i]==2) ans[i]=4;
if(flatc[i]==2) ans[i]=3;
}
tot=0;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++){
if(!ans[a[i].x] && !ans[a[i].y]){
add(a[i].x,a[i].y,a[i].w);
add(a[i].y,a[i].x,a[i].w);
}
}
for(int i=1;i<=n;i++){
if(!ans[i]){
ans[i]=2;
dfs(i,0);
}
}
if(getans){
printf("NO");
return 0;
}
if(!getans) printf("YES\n");
for(int i=1;i<=n;i++){
if(ans[i]==1) printf("A");
if(ans[i]==2) printf("B");
if(ans[i]==3) printf("C");
if(ans[i]==4) printf("D");
}
}
NOIP2023模拟13联测34#
origen#
首先对
然后原式变为
然后考虑第
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int N=2*1e5+10;
int a[N],s[N];
int f[25][3][25][3];
int ans[N];
signed main(){
freopen("origen.in","r",stdin);
freopen("origen.out","w",stdout);
int n;
while(scanf("%lld",&n)==1){
// scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
int cnt=0;
for(int i=1;i<=n;i++){
s[i]=s[i-1]^a[i];
for(int j=1;j<=20;j++){
for(int k=j;k<=20;k++){
int t1=((s[i]&(1ll<<(j-1)))>0);
int t2=((s[i]&(1ll<<(k-1)))>0);
f[j][t1][k][t2]++;
if(j==k){
ans[i]+=(1ll<<(j-1))*(1ll<<(k-1))%mod*f[j][t1^1][k][t2^1]%mod;
ans[i]%=mod;
continue;
}
ans[i]+=2*(1ll<<(j-1))*(1ll<<(k-1))%mod*f[j][t1^1][k][t2^1]%mod;
ans[i]%=mod;
}
}
ans[i]+=s[i]*s[i]%mod;
ans[i]%=mod;
cnt=(cnt+ans[i])%mod;
}
printf("%lld",cnt);
}
}
competition#
一开始写的线段树卡不过去,最后还是写的
将每个人做的题全离线到题的序列上,对题进行扫描线,考虑这道题会被做多少次,其实就是
点击查看代码
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
const int N=2*1e6+10;
const int inv2=500000004;
struct asd{
int l,r,op,x;
}a[N];
struct qwe{
int op,x;
friend bool operator <(qwe a,qwe b){
return a.x<b.x;
}
};
vector<qwe> s[N];
set<int> q;
inline int mgml(int x,int p){
int ans=1;
while(p){
if(p&1) ans=(ans*x)%mod;
x=(x*x)%mod;
p>>=1;
}
return ans;
}
int st[N],top=0;
constexpr auto SIZE (1 << 26);
char in[SIZE], *p1 = in;
inline int rnt () {
int x = 0; char c = *p1++;
while (!isdigit (c)) c = *p1++;
while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = *p1++;
return x;
}
signed main(){
freopen("competition.in","r",stdin);
freopen("competition.out","w",stdout);
fread (in, 1, SIZE, stdin);
int n,m;
n = rnt (), m = rnt ();
for(int i=1;i<=n;++i){
a[i].l = rnt (), a[i].r = rnt ();
st[++top]=a[i].l,st[++top]=a[i].r+1;
}
st[++top]=m;
sort(st+1,st+top+1);
top=unique(st+1,st+top+1)-(st+1);
for(int i=1;i<=n;i++){
int ls=lower_bound(st+1,st+top+1,a[i].l)-st;
int rs=lower_bound(st+1,st+top+1,a[i].r+1)-st;
qwe b;
b.op=1,b.x=i;
s[ls].push_back(b);
b.op=0,b.x=i;
s[rs].push_back(b);
}
q.insert(0),q.insert(n+1);
int sum=n*(n+1)/2;
int ans=0;
for(int i=1;i<=top;++i){
for(int j=0;j<s[i].size();++j){
qwe x=s[i][j];
if(x.op==1){
auto x1=q.lower_bound(x.x);
auto x2=q.upper_bound(x.x);
x1--;
int len=*x2-*x1-1;
int len1=x.x-*x1-1;
int len2=*x2-x.x-1;
sum=(sum-(len+1)*len/2%mod+(len1+1)*len1/2%mod+(len2+1)*len2/2%mod+mod)%mod;
q.insert(x.x);
}
else{
q.erase(x.x);
auto x1=q.lower_bound(x.x);
auto x2=q.upper_bound(x.x);
x1--;
int len=*x2-*x1-1;
int len1=x.x-*x1-1;
int len2=*x2-x.x-1;
sum=(sum+(len+1)*len/2%mod-(len1+1)*len1/2%mod-(len2+1)*len2/2%mod)%mod;
}
}
int cnt=(n*(n+1)/2%mod-sum+mod)%mod;
ans=(ans+(n*(n+1)/2%mod-sum+mod)%mod)%mod;
if(i!=top){
ans=(ans+cnt*((st[i+1]-st[i]-1)%mod)%mod)%mod;
}
}
int cnt=ans*mgml(n*(n+1)/2%mod,mod-2)%mod;
printf("%lld",cnt);
}
tour#
设
第一部分上
考虑在线,就跟 森林 一样,直接暴力重建较小的子树。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int inf=1e9;
int head[N*2],ver[N*2],nex[N*2],tot=0;
void add(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int f[N][50];
int a[N];
int fa[N],size[N],d[N];
int t;
struct TREE{
struct tree{
int l,r,sum;
}tr[N*256];
int rt[N],idx=0;
void change(int &p,int q,int l,int r,int wh){
p=++idx;
tr[p]=tr[q];
if(l==r){
tr[p].sum++;
return;
}
int mid=(l+r)>>1;
if(wh<=mid) change(tr[p].l,tr[q].l,l,mid,wh);
else change(tr[p].r,tr[q].r,mid+1,r,wh);
tr[p].sum=tr[tr[p].l].sum+tr[tr[p].r].sum;
}
int ask(int p,int q,int l,int r,int ls,int rs){
if(l>=ls && r<=rs) return tr[p].sum-tr[q].sum;
int mid=(l+r)>>1;
int ans=0;
if(ls<=mid) ans+=ask(tr[p].l,tr[q].l,l,mid,ls,rs);
if(rs>mid) ans+=ask(tr[p].r,tr[q].r,mid+1,r,ls,rs);
return ans;
}
}T[2];
int get_fa(int x){
if(fa[x]==x) return x;
else return get_fa(fa[x]);
}
int dis[N];
void merge(int x,int fat){
dis[x]=dis[fat]+a[x];
f[x][0]=fat;
d[x]=d[fat]+1;
for(int j=1;j<=t;j++){
f[x][j]=f[f[x][j-1]][j-1];
}
T[0].change(T[0].rt[x],T[0].rt[fat],-inf,inf,2*dis[x]-dis[f[x][0]]);
T[1].change(T[1].rt[x],T[1].rt[fat],-inf,inf,dis[x]-2*dis[f[x][0]]);
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==fat) continue;
merge(y,x);
}
}
int ask_lca(int x,int y){
if(d[x]>d[y]) swap(x,y);
for(int i=t;i>=0;i--){
if(d[f[y][i]]>=d[x]) y=f[y][i];
}
if(x==y) return x;
for(int i=t;i>=0;i--){
if(f[x][i]!=f[y][i]){
x=f[x][i],y=f[y][i];
}
}
return f[x][0];
}
int main(){
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
int testmode;
scanf("%d",&testmode);
int n,q;
scanf("%d%d",&n,&q);
T[0].tr[0].sum=T[1].tr[0].sum=0;
t=log2(n)+1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
fa[i]=i;
size[i]=1;
d[i]=1;
dis[i]=a[i];
T[0].change(T[0].rt[i],T[0].rt[0],-inf,inf,2*a[i]);
T[1].change(T[1].rt[i],T[1].rt[0],-inf,inf,a[i]);
}
int las=0;
for(int i=1;i<=q;i++){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(testmode==1){
x=(x^las),y=y^las;
}
if(!op){
add(x,y),add(y,x);
int fx=get_fa(x),fy=get_fa(y);
if(size[fx]<size[fy]){
size[fy]+=size[fx];
fa[fx]=fy;
merge(x,y);
}
else{
size[fx]+=size[fy];
fa[fy]=fx;
merge(y,x);
}
}
else{
int ans=0;
int lca=ask_lca(x,y);
ans+=T[0].ask(T[0].rt[x],T[0].rt[f[lca][0]],-inf,inf,-inf,dis[x]);
ans+=T[1].ask(T[1].rt[y],T[1].rt[lca],-inf,inf,-inf,dis[x]-dis[f[lca][0]]-dis[lca]);
printf("%d\n",ans);
las=ans;
}
}
}
NOIP2023模拟14联测35#
charlotte#
设
那么很显然当且仅当
那么假设
如果
然后考虑换根。
假设当前根为
首先你要还要维护:
首先你要算出
- 假如
是 的重儿子,那么此时的重儿子为此重儿子,然后就用到了上面维护的 , 与 ; - 相反,会更简单一些。
更新
-
然后考虑
能否成为 的最大儿子; -
如果不行就考虑能否成为此大儿子
-
均不可以;
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
const int inf=(1ll<<40);
char s[N];
bool flat[N];
int dp[N],siz[N],dis[N];
int mx[N],p[N];
int mxx[N],px[N];
struct asd{
int fa,fb;
}e[N];
int head[N*2],ver[N*2],nex[N*2],tot=0;
void add(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
void dfs(int x,int f){
if(flat[x]) siz[x]=1;
mx[x]=p[x]=0;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
dfs(y,x);
siz[x]+=siz[y];
dis[x]+=(dis[y]+siz[y]);
if(mx[x]<dis[y]+siz[y]){
mx[x]=dis[y]+siz[y];
e[x].fa=dp[y];
p[x]=y;
}
}
mxx[x]=0,px[x]=0;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f || y==p[x]) continue;
if(mxx[x]<dis[y]+siz[y]){
mxx[x]=dis[y]+siz[y];
e[x].fb=dp[y];
px[x]=y;
}
}
int res=0;
if(mx[x]>(dis[x]-mx[x])) res=mx[x]-(dis[x]-mx[x]);
else if(dis[x]%2) res=1;
dp[x]=(dis[x]-res)/2+min(res/2,dp[p[x]]);
}
int ans=inf;
void tran(int y,int x){
int res=0;
int dpx;
if(y!=p[x]){
if(mx[x]>(dis[x]-(dis[y]+siz[y])-mx[x])) res=mx[x]-(dis[x]-(dis[y]+siz[y])-mx[x]);
else if((dis[x]-(dis[y]+siz[y]))%2) res=1;
dpx=(dis[x]-(dis[y]+siz[y])-res)/2+min(res/2,e[x].fa);
}
else{
if(mxx[x]>(dis[x]-(dis[y]+siz[y])-mxx[x])) res=mxx[x]-(dis[x]-(dis[y]+siz[y])-mxx[x]);
else if((dis[x]-(dis[y]+siz[y]))%2) res=1;
dpx=(dis[x]-(dis[y]+siz[y])-res)/2+min(res/2,e[x].fb);
}
int F=siz[x]-siz[y]+dis[x]-(dis[y]+siz[y]);
if(F>mx[y]){
mxx[y]=mx[y];
px[y]=p[y];
e[y].fb=e[y].fa;
mx[y]=F;
p[y]=x;
e[y].fa=dpx;
dis[y]=F+dis[y];
siz[y]=siz[x];
int ress=0;
if(mx[y]>dis[y]-mx[y]) ress=mx[y]-(dis[y]-mx[y]);
else if(dis[y]%2) ress=1;
dp[y]=(dis[y]-ress)/2+min(ress/2,e[y].fa);
}
else if(F>mxx[y]){
px[y]=x;
mxx[y]=F;
e[y].fb=dpx;
dis[y]=F+dis[y];
siz[y]=siz[x];
int ress=0;
if(mx[y]>dis[y]-mx[y]) ress=mx[y]-(dis[y]-mx[y]);
else if(dis[y]%2) ress=1;
dp[y]=(dis[y]-ress)/2+min(ress/2,e[y].fa);
}
else{
dis[y]=dis[y]+F;
siz[y]=siz[x];
int ress=0;
if(mx[y]>dis[y]-mx[y]) ress=mx[y]-(dis[y]-mx[y]);
else if(dis[y]%2) ress=1;
dp[y]=(dis[y]-ress)/2+min(ress/2,e[y].fa);
}
}
void solve(int x,int f){
if(dp[x]*2==dis[x]) ans=min(ans,dis[x]/2);
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==f) continue;
tran(y,x);
solve(y,x);
}
}
signed main(){
freopen("charlotte.in","r",stdin);
freopen("charlotte.out","w",stdout);
int n;
scanf("%lld",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++) if(s[i]=='1') flat[i]=1;
for(int i=1;i<n;i++){
int x,y;
scanf("%lld%lld",&x,&y);
add(x,y),add(y,x);
}
dfs(1,0);
solve(1,0);
if(ans==inf) ans=-1;
printf("%lld",ans);
}
chtholly#
首先我们定义关键点为以这个点为根,至少有三个儿子的最深深度大于等于
可以发现如果蛇的头或尾到达一个这样的关键点,就可以成功掉头。
对于关键点我们可以一遍
然后判断是否关键点是否可行,这时只需要判断一个,因为一个可行的话那么全部的一定都可行,否则都不可行
那么如何判断一个点是否可行,我们可以以这个点为根然后求出一个
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int head[N*2],nex[N*2],ver[N*2],tot=0;
void add(int x,int y){
ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int n,s,t,t1,len;
int mxd[N][5],p[N][5];
int f[N][30],d[N];
int st[N],top=0;
int ask_lca(int x,int y){
if(d[x]>d[y]) swap(x,y);
for(int i=t1;i>=0;i--)
if(d[f[y][i]]>=d[x]) y=f[y][i];
if(x==y) return x;
for(int i=t1;i>=0;i--)
if(f[y][i]!=f[x][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
void init(){
t1=__lg(n)+1;
for(int j=1;j<=t1;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
void dfs1(int x,int fa){
d[x]=d[fa]+1;
f[x][0]=fa;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==fa) continue;
dfs1(y,x);
if(mxd[x][1]<mxd[y][1]+1){
mxd[x][3]=mxd[x][2];
p[x][3]=p[x][2];
mxd[x][2]=mxd[x][1];
p[x][2]=p[x][1];
mxd[x][1]=mxd[y][1]+1;
p[x][1]=y;
}
else if(mxd[x][2]<mxd[y][1]+1){
mxd[x][3]=mxd[x][2];
p[x][3]=p[x][2];
mxd[x][2]=mxd[y][1]+1;
p[x][2]=y;
}
else if(mxd[x][3]<mxd[y][1]+1 ){
mxd[x][3]=mxd[y][1]+1;
p[x][3]=y;
}
}
}
void dfs2(int x,int fa){
if(mxd[x][1]>=len && mxd[x][2]>=len && mxd[x][3]>=len) st[++top]=x;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==fa) continue;
if(y!=p[x][1]){
if(mxd[x][1]+1>mxd[y][1]){
mxd[y][3]=mxd[y][2];
p[y][3]=p[y][2];
mxd[y][2]=mxd[y][1];
p[y][2]=p[y][1];
mxd[y][1]=mxd[x][1]+1;
p[y][1]=x;
}
else if(mxd[x][1]+1>mxd[y][2]){
mxd[y][3]=mxd[y][2];
p[y][3]=p[y][2];
mxd[y][2]=mxd[x][1]+1;
p[y][2]=x;
}
else if(mxd[x][1]+1>mxd[y][3]){
mxd[y][3]=mxd[x][1]+1;
p[y][3]=x;
}
}
else{
if(mxd[x][2]+1>mxd[y][1]){
mxd[y][3]=mxd[y][2];
p[y][3]=p[y][2];
mxd[y][2]=mxd[y][1];
p[y][2]=p[y][1];
mxd[y][1]=mxd[x][2]+1;
p[y][1]=x;
}
else if(mxd[x][2]+1>mxd[y][2]){
mxd[y][3]=mxd[y][2];
p[y][3]=p[y][2];
mxd[y][2]=mxd[x][2]+1;
p[y][2]=x;
}
else if(mxd[x][2]+1>mxd[y][3]){
mxd[y][3]=mxd[x][2]+1;
p[y][3]=x;
}
}
dfs2(y,x);
}
}
int mx[N],px[N];
void dfs3(int x,int fa){
f[x][0]=fa;
d[x]=d[fa]+1;
px[x]=x;
mx[x]=0;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==fa) continue;
dfs3(y,x);
if(mx[x]<mx[y]+1){
mx[x]=mx[y]+1;
px[x]=px[y];
}
}
}
bool vis[N];
bool check(){
int lca=ask_lca(s,t);
if(s==lca || t==lca) return 1;
for(int i=1;i<=2*n;i++){
int x=px[s],len=d[x]-d[s];
if(len>=d[t]-d[lca]) return 1;
for(int j=t1;j>=0;j--){
if(len>=(1<<j)){
len-=(1<<j);
t=f[t][j];
}
}
s=x;
swap(s,t);
}
return 0;
}
int main(){
freopen("chtholly.in","r",stdin);
freopen("chtholly.out","w",stdout);
int T;
scanf("%d",&T);
int cnt=0;
while(T--){
cnt++;
scanf("%d%d%d",&n,&s,&t);
tot=0;
top=0;
memset(head,0,sizeof(int)*(n+1));
memset(mx,0,sizeof(int)*(n+1));
memset(vis,0,sizeof(bool)*(n+1));
memset(mxd,0,sizeof(mxd));
memset(p,0,sizeof(p));
for(int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs1(1,0);
init();
int lca=ask_lca(s,t);
len=d[s]+d[t]-2*d[lca];
dfs2(1,0);
if(!top){
printf("NO\n");
continue;
}
dfs3(st[1],0);
init();
if(check()) printf("YES\n");
else printf("NO\n");
}
}
作者:bloss
出处:https://www.cnblogs.com/jinjiaqioi/p/17814203.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】