zoukankan      html  css  js  c++  java
  • Luogu P2056 [ZJOI2007]捉迷藏

    动态点分治
    先建出一颗点分树,然后维护。
    对于每一个点维护两个堆,一个堆维护子树内所有点到分治父节点的距离最大值,一个堆维护一个点所有子树的第一个堆的最大值,再全局维护一个堆取所有分治重心的答案的最大值即可。
    代码细节感人。。。
    一个比较有用的trick就是用两个大根堆实现可删除的堆但是要开O2

    #include <cstdio>
    #include <queue>
    #include <cstdlib>
    using namespace std;
    #define R register
    #define LL long long
    const int MAXN=5e5+10;
    inline int max(int x,int y) { return x > y ? x : y; }
    inline int min(int x,int y) { return x < y ? x : y; }
    inline int read() {
    	int x=0,f=1; char a=getchar();
    	for(;a>'9'||a<'0';a=getchar()) if(a=='-') f=-1;
    	for(;a>='0'&&a<='9';a=getchar()) x=x*10+a-'0';
    	return x*f;
    }
    inline char getc() {
    	char a=getchar();
    	while(a!='C'&&a!='G') a=getchar();
    	return a;
    }
    inline void Print(int x) {
    	if(x>9) Print(x/10); putchar(x%10+'0');
    }
    inline void print(int x) {
    	if(x<0) putchar('-'),x=-x; Print(x); putchar('
    ');
    }
    class Heap {
    	private:
    		priority_queue<int> q1,q2;
    	public:
    	inline void push(int x) { q1.push(x); }
    	inline void erase(int x) { q2.push(x); }
    	inline int top() {
    		while(q2.size()&&q1.top()==q2.top()) q1.pop(),q2.pop();
    		return q1.top();
    	}
    	inline void pop() {
    		while(q2.size()&&q1.top()==q2.top()) q1.pop(),q2.pop();
    		q1.pop();
    	}
    	inline int top2() {
    		int mxv=top(); pop(); int res=top(); push(mxv); return res; 
    	}
    	inline int size() { return q1.size()-q2.size(); }
    };
    Heap h1[MAXN],h2[MAXN],h3;
    
    int n;
    int head[MAXN],cnt;
    struct edge { int to,next; } e[MAXN];
    inline void add(int x,int y) { e[++cnt]={y,head[x]}; head[x]=cnt; }
    
    namespace Graph {
    	int dep[MAXN],son[MAXN],siz[MAXN],fa[MAXN],top[MAXN];
    	inline void dfs1(int x,int fx) {
    		siz[x]=1; dep[x]=dep[fx]+1;fa[x]=fx;
    		for(R int i=head[x];i;i=e[i].next) {
    			int y=e[i].to; if(y==fx) continue;
    			dfs1(y,x); siz[x]+=siz[y];
    			if(siz[y]>siz[son[x]]) son[x]=y;
    		}
    	}
    	inline void dfs2(int x,int topx) {
    		top[x]=topx;
    		if(son[x]) dfs2(son[x],topx);
    		for(R int i=head[x];i;i=e[i].next) {
    			int y=e[i].to;
    			if(y==fa[x]||y==son[x]) continue;
    			dfs2(y,y);
    		}
    	}
    	inline void build() { dfs1(1,0); dfs2(1,1); }
    	inline int LCA(int x,int y) {
    		while(top[x]^top[y]) 
    			if(dep[top[x]]>dep[top[y]]) x=fa[top[x]]; else y=fa[top[y]];
    		return dep[x]<dep[y]?x:y;
    	}
    	inline int dist(int x,int y) {
    		int lca=LCA(x,y);
    		return dep[x]+dep[y]-dep[lca]*2;
    	}
    }
    namespace Tree {
    	int total;
    	int vis[MAXN],rt,siz[MAXN],mx[MAXN];
    	int fa[MAXN];
    	inline void findrt(int x,int fx) {
    		siz[x]=1; mx[x]=0;
    		for(R int i=head[x];i;i=e[i].next) {
    			int y=e[i].to;
    			if(y==fx||vis[y]) continue;
    			findrt(y,x);
    			siz[x]+=siz[y];
    			mx[x]=max(mx[x],siz[y]);
    		}
    		mx[x]=max(mx[x],total-siz[x]);
    		if(mx[x]<=mx[rt]) rt=x;
    	}
    	inline void getdis(int x,int fx,int verx) {
    		h1[rt].push(Graph::dist(x,verx));
    		for(R int i=head[x];i;i=e[i].next) { 
    			int y=e[i].to;
    			if(vis[y]||y==fx) continue;
    			getdis(y,x,verx);
    		}
    	}
    	inline void build_tree(int x,int fx) {
    		fa[x]=fx; vis[x]=1; h2[x].push(0); int sz=total;
    		for(R int i=head[x];i;i=e[i].next) {
    			int y=e[i].to; if(vis[y]) continue;
    			if(siz[y]>siz[x]) total=sz-siz[x]; else total=siz[y];
    			rt=0; findrt(y,0); getdis(rt,0,x);
    			h2[x].push(h1[rt].top()); build_tree(rt,x); 
    		}
    		if(h2[x].size()>1) h3.push(h2[x].top()+h2[x].top2());
    	}
    	inline void build() {
    		total=n; rt=0; mx[0]=1e9;
    		findrt(1,0); build_tree(rt,0);	
    	}
    	inline void off(int x) {
    		h2[x].push(0);
    		if(h2[x].size()==2) h3.push(h2[x].top()+h2[x].top2());
    		R int now=x;
    		while(fa[now]) {
    			int mxv=h1[now].size()?h1[now].top():-1;int dis=Graph::dist(x,fa[now]);
    			h1[now].push(dis); 
    			if(dis>mxv) {
    				if(h2[fa[now]].size()>1) h3.erase(h2[fa[now]].top()+h2[fa[now]].top2());
    				if(mxv^-1) h2[fa[now]].erase(mxv);
    				h2[fa[now]].push(dis);
    				if(h2[fa[now]].size()>1) h3.push(h2[fa[now]].top()+h2[fa[now]].top2());
    			} 
    			now=fa[now];
    		}
    	}
    	inline void on(int x) {
    		if(h2[x].size()==2) h3.erase(h2[x].top());
    		h2[x].erase(0);	
    		R int now=x;
    		while(fa[now]) {
    			if(h2[fa[now]].size()>1)  h3.erase(h2[fa[now]].top()+h2[fa[now]].top2());
    			h2[fa[now]].erase(h1[now].top()); h1[now].erase(Graph::dist(x,fa[now]));
    			if(h1[now].size()) h2[fa[now]].push(h1[now].top());
    			if(h2[fa[now]].size()>1) h3.push(h2[fa[now]].top()+h2[fa[now]].top2());
    			now=fa[now];
    		}
    	}
    }
    using namespace Tree;
    int sta[MAXN];
    int main() {
    //	freopen("a.in","r",stdin);
    	n=read(); int tot=n;
    	int x,y;
    	for(R int i=1;i<n;i++) { x=read(); y=read(); add(x,y); add(y,x); }
    	Graph::build(); build();
    	R int q=read();
    	while(q--) {
    		if(getc()=='C') {
    			int x=read();
    			if(sta[x]) tot++,Tree::off(x);
    			else tot--,Tree::on(x);
    			sta[x]^=1;
    		}
    		else {
    			if(tot<2) print(tot-1);
    			else print(h3.top());
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    GCD 使用说明
    iOS操作系统的层次结构
    Objective-C 类型转换
    UIView和Masonry实现动画效果
    iOS 常用手势
    SDUT 2610 Boring Counting(离散化+主席树区间内的区间求和)
    HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
    NBUT 1525 Cow Xor(01字典树+前缀思想)
    HDU 4825 Xor Sum(经典01字典树+贪心)
    HDU 1069 Monkey and Banana(二维偏序LIS的应用)
  • 原文地址:https://www.cnblogs.com/clover4/p/12828749.html
Copyright © 2011-2022 走看看