ABC218G

我们假定 \(1\) 为根,那么我们只能往叶子节点走。

于是我们可以树上 DP。

我们记录 \(f_{u}\) 表示 \(u\) 这棵子树可能的答案。

  • \(dep_u\) 为奇数时,此时必定是 Taro 操作,所以应该取子树的最大 \(f_{v}\)

  • 否则,就是 Jiro 操作,所以应该取子树的最小 \(f_{v}\)

在叶子节点时,要求当前的中位数。

我们用线段树维护,时间复杂度是 \(O(nlogn)\) 的。

这样就可以了。

My Code
#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int s=1,a=0;
	char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') s=-s;
		c=getchar();
	}
	while(isdigit(c)) {
		a=a*10+c-'0';
		c=getchar();
	}
	return s*a;
}
const int N=2e5+8;
#define ls p<<1
#define rs p<<1|1
int n,val[N];
int f[N],node[N],cnt;
struct sgt {
	int siz[N<<2];
	void update(int p) {
		siz[p]=siz[ls]+siz[rs];
	}
	void build(int l,int r,int p) {
		if(l==r) {
			siz[p]=0;
			return;
		}
		int mid=(l+r)>>1;
		build(l,mid,ls);
		build(mid+1,r,rs);
		update(p);
	}
	void change(int l,int r,int p,int x,int f) {
		if(l==r) {
			siz[p]+=f;
			return;
		}
		int mid=(l+r)>>1;
		if(x<=mid) change(l,mid,ls,x,f);
		else change(mid+1,r,rs,x,f);
		update(p);
	}
	int query(int l,int r,int p,int k) {
		if(l==r) {
			return l;
		}
		int mid=(l+r)>>1;
		if(siz[ls]>=k) return query(l,mid,ls,k);
		else return query(mid+1,r,rs,k-siz[ls]);
	}
} wgj;
int getmid() {
	if(wgj.siz[1]&1) {
		return node[wgj.query(1,cnt,1,(wgj.siz[1]+1)/2)];
	}
	else {
		int d1=wgj.query(1,cnt,1,wgj.siz[1]/2),d2=wgj.query(1,cnt,1,wgj.siz[1]/2+1);
//		cout<<d1<<" "<<d2<<endl;
		return (node[d1]+node[d2])/2;
	}
}
vector <int> G[N];
void dfs(int u,int fa,int dep) {
	wgj.change(1,cnt,1,val[u],1);
	int mx=-1,mn=0x7f7f7f7f;
	for(auto v:G[u]) {
		if(v==fa) continue;
		dfs(v,u,dep+1);
//		cout<<v<<" "<<f[v]<<endl;
		mn=min(mn,f[v]),mx=max(mx,f[v]);
	}
	if(mx==-1) /*cout<<u<<" ",*/f[u]=getmid();
	else if(dep&1) f[u]=mx;
	else f[u]=mn;
	wgj.change(1,cnt,1,val[u],-1);
}
signed main() {
	n=read();
	for(int i=1; i<=n; i++) {
		val[i]=read();
		node[i]=val[i];
	}
	sort(node+1,node+n+1);
	cnt=unique(node+1,node+n+1)-node-1;
	for(int i=1; i<=n; i++) {
		val[i]=lower_bound(node+1,node+cnt+1,val[i])-node;
	}
	wgj.build(1,cnt,1);
	for(int i=1; i<n; i++) {
		int u=read(),v=read();
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,0,1);
	printf("%d\n",f[1]);
	return 0;
}
posted @ 2021-09-12 21:10  redproblemdog  阅读(69)  评论(0编辑  收藏  举报