QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#419947#8716. 树BYR_KKKWA 0ms14476kbC++142.2kb2024-05-24 12:59:112024-05-24 12:59:11

Judging History

你现在查看的是最新测评结果

  • [2024-05-24 12:59:11]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:14476kb
  • [2024-05-24 12:59:11]
  • 提交

answer

#include<bits/stdc++.h>
#define int long long

const int maxn=2e5+10;

std::vector<int>a[maxn];

int b[maxn],n,m,q,pow2[60],lg[maxn],st[maxn][60],fa[maxn],dep[maxn];

namespace lca{
	void dfs(int now,int fat){
		dep[now]=dep[fat]+1;
		fa[now]=fat;
		for(int i:a[now]){
			if(i==fat) continue;
			dfs(i,now);
		}
	}
	void pre(){
		//处理出 st[i][j] 代表 i 在树上不算自己跳 2^j 个点到哪
		for(int i=1;i<=n;i++) st[i][0]=fa[i];
		for(int i=1;i<=lg[n]+1;i++) 
			for(int j=1;j<=n;j++) st[j][i]=st[st[j][i-1]][i-1];
	}
	int query(int x,int y){
		if(dep[x]<dep[y]) std::swap(x,y);
		//始终让 x 是深度更大的那个点
		//应该先让他们跳到同一深度
		for(int j=59;j>=0;j--){
			if(dep[st[y][j]]<dep[x]) continue;
			y=st[y][j];
		} 
		if(x==y) return x;
		//想让他们同时往上跳
		for(int j=59;j>=0;j--){
			if(st[x][j]==st[y][j]) continue;
			x=st[x][j],y=st[y][j];
		} 
		return fa[x];
	}
	int dis(int x,int y){
		if(dep[x]<dep[y]) std::swap(x,y);
		int l=query(x,y);
		return dep[x]+dep[y]-2*dep[l];
	}
}

int getans(int x,int y,int z){
	return (lca::dis(x,y)+lca::dis(y,z)==lca::dis(x,z))?(0):(1);
}

signed main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cin>>n>>m>>q;
	pow2[0]=1;
	for(int i=1;i<60;i++) pow2[i]=pow2[i-1]*2;
	lg[0]=-1;
	for(int i=1;i<=n;i++) lg[i]=lg[i>>1]+1;
	for(int i=1;i<n;i++){
		int u,v;
		std::cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	for(int i=1;i<=m;i++) std::cin>>b[i];
	lca::dfs(1,1);
	lca::pre();
	int ans=1;
	//如果要在 a[x] 处不设景点
	//当且仅当 a[x-1] -> a[x+1] 会经过 x
	//即 a[x-1] -> lca(a[x-1],a[x+1]) -> a[x+1] 会经过 x
	//这个条件满足当且仅当 dis[a[x]][a[x-1]]+dis[a[x]][a[x+1]]==dis[a[x-1]][a[x+1]]
	//显然, a[1] 和 a[n] 是必须设景点的 
	for(int i=2;i<n;i++) ans+=getans(b[i-1],b[i],b[i+1]);
	while(q--){
		int p,w;
		std::cin>>p>>w;
		for(int i=p-1;i<=p+1;i++){
			if(i<1||i>n) continue;
			if(i-1<1||i+1>n) continue;
			ans-=getans(b[i-1],b[i],b[i+1]);
		}
		b[p]=w;
		for(int i=p-1;i<=p+1;i++){
			if(i<1||i>n||i-1<1||i+1>n) continue;
			ans+=getans(b[i-1],b[i],b[i+1]); 
		}
		std::cout<<ans<<'\n';
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 14476kb

input:

5 5 3
2 1
3 2
1 4
5 1
1 5 4 2 3
1 3
5 3
3 3

output:

4
4
4

result:

wrong answer 3rd numbers differ - expected: '5', found: '4'