题解 Defence

传送门

发现最少次数只和最左,最右及中间最长的全0段有关
本来想启发式合并,结果发现直接线段树合并搭配一个类似山海经的方法就可以过了

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long 
#define pb push_back
//#define int long long 

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, q;
int head[N], size, ans[N];
vector<int> pos[N];
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {edge* k=&e[++size]; k->to=t; k->next=head[s]; head[s]=size;}

namespace force{
	vector<int> line[N];
	void dfs(int u) {
		for (int i=head[u],v; i; i=e[i].next) {
			v = e[i].to;
			dfs(v);
			for (auto it:line[v]) line[u].pb(it);
		}
		for (auto it:pos[u]) line[u].pb(it);
		sort(line[u].begin(), line[u].end());
		int usize=unique(line[u].begin(), line[u].end())-line[u].begin();
		line[u].resize(usize);
		//cout<<"at "<<u<<": "; for (auto it:line[u]) cout<<it<<' '; cout<<endl;
		int l, mid=0, r;
		if (line[u].size()==0) {ans[u]=-1; return ;}
		l=line[u][0]-1; r=m-line[u][line[u].size()-1];
		for (vector<int>::iterator it=line[u].begin(); it+1!=line[u].end(); ++it) {
			mid=max(mid, *(it+1)-*it-1);
		}
		//cout<<"line: "<<l<<' '<<mid<<' '<<r<<endl;
		ans[u]=max(l+r, mid);
	}
	void solve() {
		dfs(1);
		for (int i=1; i<=n; ++i) printf("%d\n", ans[i]);
		exit(0);
	}
}

namespace task{
	int siz[N], msiz[N], mson[N], l[N], mid[N], r[N];
	const int SIZE=N*55;
	int tl[SIZE], tr[SIZE], lst[SIZE], rst[SIZE], lmax[SIZE], rmax[SIZE], mmax[SIZE], lson[SIZE], rson[SIZE], rot[N], tot;
	bool exi[SIZE];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define lst(p) lst[p]
	#define rst(p) rst[p]
	#define lmax(p) lmax[p]
	#define rmax(p) rmax[p]
	#define mmax(p) mmax[p]
	#define l(p) lson[p]
	#define r(p) rson[p]
	#define exi(p) exi[p]
	void pushup(int p) {
		exi(p)=exi(l(p))|exi(r(p));
		if (!exi(p)) return ;
		lst(p)=min(lst(l(p)), lst(r(p)));
		rst(p)=max(rst(l(p)), rst(r(p)));
		lmax(p)=lst(p)-tl(p); rmax(p)=tr(p)-rst(p);
		mmax(p)=max(rmax(l(p))+lmax(r(p)), max(mmax(l(p)), mmax(r(p))));
		//mmax(p)=max(lst(r(p))-rst(l(p))-1, max(mmax(l(p)), mmax(r(p))));
		//cout<<"pushup "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<lst(p)<<' '<<rst(p)<<' '<<lmax(p)<<' '<<rmax(p)<<' '<<mmax(p)<<endl;
	}
	void upd(int& p, int l, int r, int pos) {
		if (!p) {p=++tot; tl(p)=l; tr(p)=r;}
		if (l==r) {exi(p)=1; lst(p)=rst(p)=pos; return ;}
		int mid=(l+r)>>1;
		if (pos<=mid) upd(l(p), l, mid, pos);
		else upd(r(p), mid+1, r, pos);
		pushup(p);
	}
	int merge(int p1, int p2) {
		if (!(p1&&p2)) return p1|p2;
		if (tl(p1)==tr(p1)) {
			exi(p1)|=exi(p2);
			lst(p1)|=lst(p2);
			rst(p1)|=rst(p2);
			return p1;
		}
		l(p1)=merge(l(p1), l(p2));
		r(p1)=merge(r(p1), r(p2));
		pushup(p1);
		return p1;
	}
	
	void dfs1(int u) {
		siz[u]=pos[u].size();
		for (int i=head[u],v; i; i=e[i].next) {
			v = e[i].to;
			dfs1(v);
			siz[u]+=siz[v];
			if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
		}
	}
	void dfs2(int u) {
		//cout<<"dfs2 "<<u<<endl;
		for (int i=head[u],v; i; i=e[i].next) {
			v = e[i].to;
			dfs2(v);
		}
		
		rot[u]=rot[mson[u]];
		
		for (int i=head[u],v; i; i=e[i].next) {
			v = e[i].to;
			if (v==mson[u]) continue;
			rot[u]=merge(rot[u], rot[v]);
		}
		
		for (auto it:pos[u]) upd(rot[u], 1, m, it);
		
		//cout<<"line"<<u<<": "<<(lst(rot[u])-1)<<' '<<(m-rst(rot[u]))<<' '<<mmax(rot[u])<<endl;
		ans[u] = max((lst(rot[u])-1)+(m-rst(rot[u])), mmax(rot[u]));
		if (ans[u]>m) ans[u]=-1;
	}
	void solve() {
		//memset(lst, 0x3f, sizeof(lst));
		//cout<<double(sizeof(tl)*10+sizeof(siz)*5)/1024/1024<<endl;
		lst(0)=INF;
		dfs1(1); dfs2(1);
		//cout<<"rst: "<<rst(rot[1])<<endl;
		for (int i=1; i<=n; ++i) printf("%d\n", ans[i]);
		exit(0);
	}
}

signed main()
{
	n=read(); m=read(); q=read();
	for (int i=1,u,v; i<n; ++i) {
		u=read(); v=read();
		add(u, v);
	}
	for (int i=1,u; i<=q; ++i) {u=read(); pos[u].pb(read());}
	//force::solve();
	task::solve();
	
	return 0;
}
posted @ 2021-08-08 15:55  Administrator-09  阅读(12)  评论(0编辑  收藏  举报