zoukankan      html  css  js  c++  java
  • 动态点分治总结

    动态点分治总结

    下面是伟大の分割线!

    上面是伟大の分割线!

    废话

    再开一坑。

    刷几道题来填。

    才刷两题,慢慢补吧。。。。

    (这玩意是真的神,调死你

    警告:这篇文章中的代码都很丑陋!

    下面是伟大の分割线!

    上面是伟大の分割线!

    思想

    前置技能:点分治。

    动态点分治就是带修改的点分治。

    如果每次单点修改之后重新点分治一遍,被影响到的节点最多(log_2n)个。

    然后就有了动态点分治。。。。

    点分树

    我也不知道这个叫什么反正就是一颗新树。。。

    构建方法大概就是点分治solve的时候顺便搞出,它就是solve时的搜索树(?)

    可以证明那玩意深度是严格(log_2n)的。

    如果修改一个点,只需在对应点分树上修改(暴跳父亲,慢慢修改)

    查询也可以暴跳父亲,但有些题不用

    下面是伟大の分割线!

    上面是伟大の分割线!

    例题

    cogs2036 捉迷藏

    查询最长链。

    要维护三种堆= =不看题解写不出= = = = = = = = =

    (其实应该是multiset= =但是能用堆来模拟)

    首先每个点维护一个堆1,是子树到这个点的距离。(“子树”是点分树,“距离”是原树上的距离)

    再维护一个堆2,是所有子树的堆1堆顶

    再全局维护一个堆3,是所有点堆2的最大和次大(这里要讨论一下,如果这个点是黑色的,少了的元素用0补上;如果是白色的堆又没有两个元素,就是0)

    真•奇丑无比

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<vector>
    #define il inline
    #define rg register
    #define vd void
    #define sta static
    typedef long long ll;
    using namespace std;
    il int gi(){
    	rg int x=0,f=1;rg char ch=getchar();
    	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    const int maxn=100001; 
    #define queue priority_queue
    struct Queue{
    	queue<int>que,del;
    	il int siz(){return que.size()-del.size();}
    	il int top(){
    		if(siz()<1)return 0;
    		while(!del.empty()&&que.top()==del.top())que.pop(),del.pop();
    		return que.top();
    	}
    	il vd pop(int x){del.push(x);}
    	il vd push(int x){que.push(x);}
    };
    int n,q,fir[maxn],dis[maxn<<1],nxt[maxn<<1],col[maxn],dep[maxn],id;
    il vd link(int x,int y){nxt[++id]=fir[x],fir[x]=id,dis[id]=y;}
    Queue que[maxn],Que[maxn],QUE;
    int siz[maxn],f[maxn],rt,vis[maxn],sum,FAQ[maxn];
    il vd getrt(int x,int FA){
    	f[x]=0;siz[x]=1;
    	for(int i=fir[x];i;i=nxt[i]){
    		if(vis[dis[i]]||FA==dis[i])continue;
    		getrt(dis[i],x);
    		siz[x]+=siz[dis[i]];
    		f[x]=max(f[x],siz[dis[i]]);
    	}
    	f[x]=max(f[x],sum-siz[x]);
    	if(f[x]<f[rt])rt=x;
    }
    il vd Getrt(int x,int _sum){sum=_sum,rt=0,f[0]=2e9,getrt(x,-1);}
    vector<int>S[maxn];int Root;
    il vd solve(int x){
    	vis[x]=1;
    	for(int i=fir[x];i;i=nxt[i]){
    		if(vis[dis[i]])continue;
    		Getrt(dis[i],siz[dis[i]]);
    		FAQ[rt]=x;S[x].push_back(rt);
    		solve(rt);
    	}
    }
    int st[17][maxn];
    il vd Getdep(int x,int FA=-1){
    	for(int i=fir[x];i;i=nxt[i]){
    		if(FA==dis[i])continue;
    		dep[dis[i]]=dep[x]+1;
    		st[0][dis[i]]=x;
    		Getdep(dis[i],x);
    	}
    }
    il int dist(int x,int y){
    	int ret=dep[x]+dep[y],cha=dep[x]-dep[y];
    	if(dep[x]<dep[y])cha=-cha,swap(x,y);
    	for(int i=16;~i;--i)if(cha&(1<<i))x=st[i][x];
    	for(int i=16;~i;--i)if(st[i][x]^st[i][y])x=st[i][x],y=st[i][y];
    	if(x^y)x=st[0][x];
    	return ret-2*dep[x];
    }
    il vd calc(int x,int FA,int Rt){
    	que[Rt].push(dist(x,FAQ[Rt]));
    	for(vector<int>::iterator i=S[x].begin();i!=S[x].end();++i){
    		if(FA==*i)continue;
    		calc(*i,x,Rt);
    	}
    }
    il int Top(int x){
    	sta int a,b,ret;
    	a=Que[x].top();Que[x].pop(a);
    	b=Que[x].top();Que[x].push(a);
    	if(col[x])ret=a+b;
    	else if(a&&b)ret=a+b;
    	else ret=0;
    	return ret;
    }
    il vd Solve(int x){
    	calc(x,-1,x);
    	for(vector<int>::iterator i=S[x].begin();i!=S[x].end();++i){
    		Solve(*i);
    		Que[x].push(que[*i].top());
    	}
    	QUE.push(Top(x));
    }
    int main(){
    	freopen("hide.in","r",stdin);
    	freopen("hide.out","w",stdout);
    	n=gi();int x,y,tot=n;
    	for(rg int i=1;i<=n;++i)col[i]=1;
    	for(rg int i=1;i<n;++i)x=gi(),y=gi(),link(x,y),link(y,x);
    	Getrt(1,n),Root=rt,solve(rt);
    	dep[1]=0,Getdep(1);
    	for(rg int i=1;i<17;++i)
    		for(rg int j=1;j<=n;++j)
    			st[i][j]=st[i-1][st[i-1][j]];
    	Solve(Root);
    	q=gi();char opt[5];
    	while(q--){
    		scanf("%s",opt);
    		if(opt[0]=='G'){
    			if(tot<2)printf("%d
    ",tot-1);
    			else printf("%d
    ",QUE.top());
    		}
    		else{
    			x=gi();y=1;
    			for(rg int i=x;i;i=FAQ[i]){
    				if(FAQ[i])QUE.pop(Top(FAQ[i]));
    				if(FAQ[i])Que[FAQ[i]].pop(que[i].top());
    				col[x]?que[i].pop(dist(FAQ[i],x)):que[i].push(dist(FAQ[i],x));
    				if(FAQ[i])Que[FAQ[i]].push(que[i].top());
    				if(FAQ[i])QUE.push(Top(FAQ[i]));
    			}
    			QUE.pop(Top(x));
    			if(col[x])--tot;else++tot;
    			col[x]^=1;
    			QUE.push(Top(x));
    		}
    	}
    	return 0;
    }
    

    bzoj3730 震波

    每个点维护两颗线段树。。。这不看题解咋搞

    第一颗存子树对这个点的贡献,下标是子树的点到这个点的距离,存的值是这些点的权值和

    第二颗存子树对父亲的贡献,下标是到父亲的距离,存的是这些点的权值和

    剩下都看题解写的。。。。。。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define il inline
    #define rg register
    #define vd void
    #define sta static
    using namespace std;
    il int gi(){
    	rg int x=0,f=1;rg char ch=getchar();
    	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    const int maxn=100001,maxm=maxn<<1;
    int n,m,lg,val[maxn];
    typedef const int& cni;
    namespace sgt{
    	const int maxd=20000000;
    	int index,root1[maxn],root2[maxn],ls[maxd],rs[maxd],sum[maxd];
    #define mid ((l+r)>>1)
    	il vd update(int&x,int l,int r,cni p,cni k){
    		if(!x)x=++index;sum[x]+=k;
    		if(l==r)return;
    		if(p<=mid)update(ls[x],l,mid,p,k);
    		else update(rs[x],mid+1,r,p,k);
    	}
    	il int query(cni x,int l,int r,cni R){
    		if(!sum[x]||R<l)return 0;
    		if(r<=R)return sum[x];
    		return query(ls[x],l,mid,R)+query(rs[x],mid+1,r,R);
    	}
    }
    
    namespace Divide{
    	int fir[maxn],dis[maxm],nxt[maxm],id,rt;
    	il vd link(cni x,cni y){nxt[++id]=fir[x],fir[x]=id,dis[id]=y;}
    	namespace SLPF{
    		int dep[maxn],fa[maxn],siz[maxn],top[maxn],son[maxn];
    		il vd DFS(cni x){
    			siz[x]=1;
    			for(int i=fir[x];i;i=nxt[i])
    				if(dis[i]^fa[x]){
    					dep[dis[i]]=dep[x]+1,fa[dis[i]]=x;
    					DFS(dis[i]);
    					siz[x]+=siz[dis[i]];
    					if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
    				}
    		}
    		il vd DFS2(cni x,cni tp){
    			top[x]=tp;
    			if(son[x])DFS2(son[x],tp);
    			for(int i=fir[x];i;i=nxt[i])
    				if((dis[i]^fa[x])&&(dis[i]^son[x]))
    					DFS2(dis[i],dis[i]);
    		}
    		il int dist(int x,int y){
    			int ret=dep[x]+dep[y];
    			while(top[x]^top[y])
    				if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
    				else y=fa[top[y]];
    			if(dep[y]<dep[x])x=y;
    			return ret-dep[x]*2;
    		}
    	}
    	namespace DFZ{
    		int f[maxn],siz[maxn],FAQ[maxn],sum,vis[maxn];
    		il vd getrt(cni x,cni FA){
    			f[x]=0,siz[x]=1;
    			for(int i=fir[x];i;i=nxt[i]){
    				if(FA==dis[i]||vis[dis[i]])continue;
    				getrt(dis[i],x);
    				siz[x]+=siz[dis[i]],f[x]=max(f[x],siz[dis[i]]);
    			}
    			f[x]=max(f[x],sum-siz[x]);
    			if(f[x]<f[rt])rt=x;
    		}
    		il vd Getrt(cni x,cni _sum){f[0]=2e9,sum=_sum,rt=0,getrt(x,-1);}
    		il vd Build(int x){
    			vis[x]=1;
    			for(int i=fir[x];i;i=nxt[i]){
    				if(vis[dis[i]])continue;
    				Getrt(dis[i],siz[dis[i]]);
    				FAQ[rt]=x;Build(rt);
    			}
    		}
    	}
    	il int Query(int x,int k){
    		int ret=sgt::query(sgt::root1[x],1,n,k+1),yyb=0;
    		for(int i=x;DFZ::FAQ[i];i=DFZ::FAQ[i]){
    			yyb=SLPF::dist(x,DFZ::FAQ[i]);
    			ret+=sgt::query(sgt::root1[DFZ::FAQ[i]],1,n,k-yyb+1);
    			ret-=sgt::query(sgt::root2[i],1,n,k-yyb+1);
    		}
    		return ret;
    	}
    	il vd Update(int x,int y){
    		sgt::update(sgt::root1[x],1,n,1,y);int yyb=0;
    		for(int i=x;DFZ::FAQ[i];i=DFZ::FAQ[i]){
    			yyb=SLPF::dist(x,DFZ::FAQ[i]);
    			sgt::update(sgt::root1[DFZ::FAQ[i]],1,n,yyb+1,y);
    			sgt::update(sgt::root2[i],1,n,yyb+1,y);
    		}
    	}
    	il vd Prepare(){
    		DFZ::Getrt(1,n);
    		SLPF::DFS(1),SLPF::DFS2(1,1);
    		DFZ::Build(rt);
    		for(rg int i=1;i<=n;++i)Update(i,val[i]);
    	}
    }
    int main(){
    #ifdef xzz
    	freopen("orz.in","r",stdin);
    	freopen("orz.out","w",stdout);
    #endif
    	int opt,u,v,lst=0;
    	n=gi(),m=gi();lg=log2(n);
    	for(rg int i=1;i<=n;++i)val[i]=gi();
    	for(rg int i=1;i<n;++i)u=gi(),v=gi(),Divide::link(u,v),Divide::link(v,u);
    	Divide::Prepare();		
    	while(m--){
    		opt=gi(),u=gi(),v=gi();
    #ifdef ONLINE_JUDGE
    		u^=lst,v^=lst;
    #endif
    		if(opt==0)lst=Divide::Query(u,v),printf("%d
    ",lst);
    		else Divide::Update(u,v-val[u]),val[u]=v;
    	}
    	return 0;
    }
    

    bzoj4372 烁烁的游戏

    我™放弃了。。。

    哪天想起来了再补吧

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #define il inline
    #define rg register
    #define vd void
    #define sta static
    typedef long long ll;
    il int gi(){
    	rg int x=0,f=1;rg char ch=getchar();
    	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    const int maxn=maxm;
    typedef const int& ci;
    int n,m;
    namespace sgt{
    	int maxd=2e7;
    	int ls[maxd],rs[maxd],sum[maxd],idx;
    #define mid ((l+r)>>1)
    	il vd update(int&x,int l,int r,ci p,ci k){
    		if(!x)x=++idx;sum[x]+=k;
    		if(l==r)return;
    		if(mid<p)update(rs[x],mid+1,r,p,k);
    		else update(ls[x],l,mid,p,k);
    	}
    	il int query(ci x,int l,int r,ci L,ci R){
    		if(!sum[x]||R<l||r<L)return 0;
    		if(L<=l&&r<=R)return sum[x];
    		return query(ls[x],l,mid,L,R)+query(rs[x],mid+1,r,L,R);
    	}
    #undef mid
    }
    namespace Tree{
    	int fir[maxn],nxt[maxn<<1],dis[maxn<<1],idx;
    	il vd link(ci x,ci y){nxt[++id]=fir[x],fir[x]=id,dis[id]=y;}
    	namespace SLPF{
    		int root[maxn],root2[maxn],siz[maxn],dep[maxn],fa[maxn],son[maxn],top[maxn];
    		il vd dfs(ci x){
    			siz[x]=1;
    			for(int i=fir[x];i;i=nxt[i]){
    				if(fa[x]==i)continue;
    				fa[dis[i]]=x;
    				dep[dis[i]]=dep[x]+1;
    				dfs(dis[i]);
    				if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
    			}
    		}
    		il vd dfs2(ci x,ci tp){
    			top[x]=tp;
    			if(son[x])dfs2(son[x],tp);
    			for(int i=fir[x];i;i=nxt[i]){
    				if(fa[x]==i||son[x]==i)continue;
    				dfs2(dis[i],dis[i]);
    			}
    		}
    		il int dist(int x,int y){
    			int ret=dep[x]+dep[y];
    			while(top[x]^top[y])
    				if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
    				else y=fa[top[y]];
    			if(dep[x]>dep[y])x=y;
    			return ret-dep[x]*2;
    		}
    	}namespace DFZ{
    		int siz[maxn],f[maxn],rt,sum;bool vis[maxn];
    		il vd getrt(ci x,ci FA){
    			siz[x]=1,f[x]=0;
    			for(int i=fir[x];i;i=nxt[i]){
    				if(FA==dis[i]||vis[dis[i]])continue;
    				getrt(dis[i],x);
    				siz[x]+=siz[dis[i]];
    				f[x]=max(f[x],siz[dis[i]]);
    			}
    			f[x]=max(f[x],sum-siz[dis[i]]);
    			if(f[x]<f[rt])rt=x;
    		}
    		il vd Getrt(ci x,ci _sum){f[0]=2e9,rt=0,sum=_sum,getrt(x,-1);}
    		il vd build(ci x){
    		    vis[x]=1;
    		    for(int i=fir[x];i;i=nxt[i]){
    		        if(vis[dis[i]])continue;
    		        Getrt(dis[i],siz[dis[i]]);
    		        FAQ[rt]=x;
    		        build(rt);
    		    }
    		}
    	}
    	il vd prepare(){
    	    int u,v;
    	    for(rg int i=1;i<n;++i)u=gi(),v=gi(),link(u,v),link(v,u);
    	    DFZ::Getrt(1,n),DFZ::build(DFZ::rt);
    	    SLPF::dfs(1),SLPF::dfs2(1);
    	}
    	il vd Update(int x,int d,int w){
    	    sgt::update(root[x],1,n,d+1,w);
            for(rg int i=FAQ[x];FAQ[i];i=FAQ[i]){
    			int dst=SLPF::dist(x,FAQ[i]);
    			sgt::update(sgt::root[FAQ[i]],1,n,1,w);
    			sgt::update(sgt::root2[i],1,n,1,w);
    			sgt::update(sgt::root[FAQ[i]],1,n,dst+2,-w);
    			sgt::update(sgt::root2[i],1,n,dst+2,-w);
    		}
    	}
    	il int Query(int x){
    		int ret=sgt::query(root[x],);
    	}
    }
    int main(){
    	freopen("orz.in","r",stdin);
    	freopen("orz.out","w",stdout);
    	n=gi(),m=gi();
    	
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/xzz_233/p/8301050.html
Copyright © 2011-2022 走看看