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;
    }
    
  • 相关阅读:
    第六周学习心得
    syncnavigator关于win10、win8系统无法注册机进行激活的问题
    使用SyncNavigator轻松实现数据库异地同步、断点续传、异构同步
    数据库同步的正确打开方式
    使用SyncNavigator实现数据库异地同步。
    聊聊MySQL主从数据库同步的那些事儿
    高并发架构系列:数据库主从同步的3种一致性方案实现,及优劣比较
    MySQL binlog数据库同步技术总结
    数据库同步的两种方式
    某省肿瘤医院 — 数据备份 + 数据库同步
  • 原文地址:https://www.cnblogs.com/xzz_233/p/8301050.html
Copyright © 2011-2022 走看看