QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#327659#3307. Query on a Tree 17yz_lyWA 2ms9884kbC++143.0kb2024-02-15 11:47:012024-02-15 11:47:01

Judging History

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

  • [2024-02-15 11:47:01]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:9884kb
  • [2024-02-15 11:47:01]
  • 提交

answer

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}
inline void work(int k){
	if(k<0){
		putchar('-');
		k=-k;
	}
	if(k>9)
		work(k/10);
	putchar(k%10+'0');
}
/*
现将dfs序搞下来变成一个序列
容易发现第一个满足前缀和>=sum/2的点一定在带权重心
直接倍增跳就行了
*/
int n,q,cnt,first[100005],siz[100005],son[100005],dep[100005],fa[100005],dp[100005],dfn[100005],rev[100005],num,dp1[100005][25];
struct q1{
	int u,w,nex;
}a[200005];
void add(int u1,int w1){
	a[++cnt]={u1,w1,first[u1]};
	first[u1]=cnt;
}
void dfs(int u,int dad){
	dp1[u][0]=dad;
	for(int i=1;i<=20;i++){
		dp1[u][i]=dp1[dp1[u][i-1]][i-1];
	}
	dep[u]=dep[dad]+1;
	fa[u]=dad;
	siz[u]=1;
	for(int i=first[u];i;i=a[i].nex){
		if(a[i].w==dad)
			continue;
		dfs(a[i].w,u);
		siz[u]+=siz[a[i].w];
		if(siz[son[u]]<siz[a[i].w])
			son[u]=a[i].w;
	}
}
void dfs1(int u,int t){
	dp[u]=t;
	dfn[u]=++num;
	rev[num]=u;
	if(son[u])
		dfs1(son[u],t);
	for(int i=first[u];i;i=a[i].nex){
		if(a[i].w==fa[u]||a[i].w==son[u])
			continue;
		dfs1(a[i].w,a[i].w);
	}
}
struct node{
	ll val[400005],lazy[400005];
	void pushdown(int k,int l,int r){
		int mid=(l+r)>>1;
		val[2*k]+=lazy[k]*(mid-l+1);
		val[2*k+1]+=lazy[k]*(r-mid);
		lazy[2*k]+=lazy[k];
		lazy[2*k+1]+=lazy[k];
		lazy[k]=0;
	}
	void change(int k,int l,int r,int x,int y,ll v){
		if(l>y||r<x)
			return ;
		if(l>=x&&r<=y){
			val[k]+=(r-l+1)*v;
			lazy[k]+=v;
			return ;
		}
		pushdown(k,l,r);
		int mid=(l+r)>>1;
		change(2*k,l,mid,x,y,v);
		change(2*k+1,mid+1,r,x,y,v);
		val[k]=val[2*k]+val[2*k+1];
	}
	ll query(int k,int l,int r,int x,int y){
		if(l>y||r<x)
			return 0;
		if(l>=x&&r<=y)
			return val[k];
		pushdown(k,l,r);
		int mid=(l+r)>>1;
		return query(2*k,l,mid,x,y)+query(2*k+1,mid+1,r,x,y);
	}
}tree;
int main(){
	n=read();
	for(int i=1,x,y;i<n;i++){
		x=read();
		y=read();
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	dfs1(1,1);
	q=read();
	while(q--){
		int f=read(),u=read(),v;
		if(f==1)
			tree.change(1,1,n,dfn[u],dfn[u]+siz[u]-1,1);
		else{
			v=read();
			int x=u,y=v;
			while(dp[x]!=dp[y]){
				if(dep[dp[x]]>dep[dp[y]])
					swap(x,y);
				tree.change(1,1,n,dfn[dp[y]],dfn[y],1);
				y=fa[dp[y]];
			}
			if(dep[x]>dep[y])
				swap(x,y);
			tree.change(1,1,n,dfn[x],dfn[y],1);
		}
		int l=1,r=n+1;
		ll sum=tree.query(1,1,n,1,n);
		while(l<r){
			int mid=(l+r)>>1;
			if(tree.query(1,1,n,1,mid)>=sum/2.0)
				r=mid;
			else
				l=mid+1;
		}
		l=rev[l];
		// cerr<<l<<" "<<sum<<"\n";
		for(int i=20;i>=0;i--){
			int now=dp1[l][i];
			if(now&&tree.query(1,1,n,dfn[now],dfn[now]+siz[now]-1)<=sum/2.0)
				l=now;
		}
		if(sum==1)
			work(u);
		else
			work(dp1[l][0]);
		putchar('\n');
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 7672kb

input:

7
1 6
1 7
7 3
3 2
7 5
5 4
4
1 2
1 4
1 6
2 6 7

output:

2
7
7
1

result:

ok 4 lines

Test #2:

score: 0
Accepted
time: 2ms
memory: 9884kb

input:

15
1 2
1 3
2 4
3 7
6 2
3 8
4 9
2 5
5 11
7 13
10 4
11 15
12 5
14 7
11
2 6 11
1 6
2 10 9
1 9
2 2 6
1 4
2 7 6
1 2
2 8 13
1 10
2 8 15

output:

2
2
2
2
2
2
2
2
2
2
2

result:

ok 11 lines

Test #3:

score: -100
Wrong Answer
time: 1ms
memory: 7784kb

input:

2
1 2
1
1 1

output:

0

result:

wrong answer 1st lines differ - expected: '1', found: '0'