zoukankan      html  css  js  c++  java
  • 【ZJOI2007】—捉迷藏(动态点分治)

    传送门

    网上主要做法有2种:

    1、括号序列(然而我并不会)

    简单的动态点分治

    建出点分树之后每次lognlogn修改就是了

    实现的时候维护三个堆
    A:A:全局一个堆,维护答案最大值,存每个堆B的最大值和次大值之和
    B:B:每个重心存各个子树最大值,即子结点堆C的最大值
    C:C:每个重心存所有子树到其距离

    然后每次查询AA中最大值就可以了

    然后我们用欧拉序+STST表维护LcaLca

    复杂度O(nlog2n+mlog2n)O(nlog^2n+mlog^2n)

    STLSTL常数较大,不吸氧很容易TT

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    #define ll long long
    const int N=100005;
    int two[20],Log[200005];
    int n,m,rt,tot;
    int siz[N],fa[N],dep[N],cnt,maxn,son[N],adj[N],nxt[N<<1],to[N<<1];
    int st[18][N<<1],pos[N],dfn;
    bool vis[N],op[N];
    inline void addedge(int u,int v){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    }
    struct Stargazer{
    	priority_queue<int>A,B;
    	inline void push(int x){
    		A.push(x);
    	}
    	inline void erase(int x){
    		B.push(x);
    	}
    	inline void pop(){
    		while(B.size()&&A.top()==B.top())
    			A.pop(),B.pop();
    		A.pop();
    	}
    	inline int top(){
    		while(B.size()&&A.top()==B.top())
    			A.pop(),B.pop();
    		if(!A.size())return 0;
    		return A.top();
    	}
    	inline int size(){
    		return A.size()-B.size();
    	}
    	inline int sec(){
    		if(size()<2)return 0;
    		int x=top();pop();
    		int y=top();push(x);
    		return y;
    	}
    }A,B[N],C[N];
    inline void init(){
    	two[0]=1,Log[0]=-1;
    	for(int i=1;i<20;++i)two[i]=two[i-1]*2;
    	for(int i=1;i<=200000;++i)Log[i]=Log[i>>1]+1;
    }
    void dfs(int u,int f){
    	st[0][++dfn]=dep[u];
    	pos[u]=dfn;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==f)continue;
    		dep[v]=dep[u]+1;
    		dfs(v,u);
    		st[0][++dfn]=dep[u];
    	}
    }
    inline void pre(){
    	for(int i=1;i<=Log[dfn];++i)
    		for(int j=1;j<=dfn;++j)
    			if(j+two[i]-1<=dfn)
    				st[i][j]=min(st[i-1][j],st[i-1][j+two[i-1]]);
    }
    void getrt(int u,int fa){
    	siz[u]=1,son[u]=0;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==fa||vis[v])continue;
    		getrt(v,u);
    		siz[u]+=siz[v];
    		son[u]=max(son[u],siz[v]);
    	}
    	son[u]=max(son[u],maxn-siz[u]);
    	if(son[u]<son[rt])rt=u;
    }
    void solve(int u,int f){
    	fa[u]=f,vis[u]=1;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(vis[v])continue;
    		maxn=siz[v],rt=0;
    		getrt(v,u);
    		solve(rt,u);
    	}
    }
    inline int lca(int u,int v){
    	u=pos[u],v=pos[v];
    	if(v<u)swap(v,u);
    	int L=Log[v-u+1];
    	return min(st[L][u],st[L][v-two[L]+1]);
    }
    inline int dis(int u,int v){
    	return dep[u]+dep[v]-2*lca(u,v);
    }
    void off(int u,int v){
    	if(u==v){
    		B[u].push(0);
    		if(B[u].size()==2)A.push(B[u].top());
    	}
    	if(!fa[u])return;
    	int f=fa[u],d=dis(f,v),tmp=C[u].top();
    	C[u].push(d);
    	if(d>tmp){
    		int mx=B[f].top()+B[f].sec(),si=B[f].size();
    		if(tmp)B[f].erase(tmp);
    		B[f].push(d);int now=B[f].top()+B[f].sec();
    		if(now>mx){
    			if(si>=2)A.erase(mx);
    			if(B[f].size()>=2)A.push(now);
    		}
    	}
    	off(f,v);
    }
    void on(int u,int v){
    	if(u==v){
    		if(B[u].size()==2)A.erase(B[u].top());
    		B[u].erase(0);
    	}
    	if(!fa[u])return;
    	int f=fa[u],d=dis(f,v),tmp=C[u].top();
    	C[u].erase(d);
    	if(d==tmp){
    		int mx=B[f].top()+B[f].sec(),si=B[f].size();
    		B[f].erase(d);
    		if(C[u].top())B[f].push(C[u].top());
    		int now=B[f].top()+B[f].sec();
    		if(now<mx){
    			if(si>=2)A.erase(mx);
    			if(B[f].size()>=2)A.push(now);
    		}
    	}
    	on(f,v);
    }
    int main(){
    	init();
    	n=read();
    	for(int i=1;i<n;++i){
    		int u=read(),v=read();
    		addedge(u,v),addedge(v,u);
    	}
    	dfs(1,0);
    	pre();
    	son[0]=maxn=n;
    	getrt(1,rt=0),solve(rt,0);
    	for(int i=1;i<=n;i++)C[i].push(0);
    	for(int i=1;i<=n;i++)op[i]=1;
    	for(int i=1;i<=n;++i)
    		off(i,i),++tot;
    	char c[5];m=read();
    	for(int i=1;i<=m;++i){
    		scanf("%s",c);
    		if(c[0]=='G'){
    			if(tot<=1)cout<<(tot-1)<<'
    ';
    			else cout<<A.top()<<'
    ';
    		}
    		else{
    			int u=read();
    			if(op[u])on(u,u),--tot;
    			else off(u,u),++tot;
    			op[u]^=1;
    		}
    	}
    }
    
  • 相关阅读:
    第十八章 并发登录人数控制——《跟我学Shiro》(http://blog.csdn.net/lhacker/article/details/19334305)
    spring4 hibernate4 transaction
    sqllite
    http://www.cnblogs.com/enshrineZither/p/3793459.html
    MyBatis 显示日志
    Centos7配置更新国内yum源
    解决Centos运行yum 报错:坏的解释器
    用python生成基于lombok 和 hibernate 生成javabean
    数据库事务中的隔离级别和锁+spring Transactional注解
    springmvc 通过异常增强返回给客户端统一格式
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366356.html
Copyright © 2011-2022 走看看