zoukankan      html  css  js  c++  java
  • 【BZOJ4538】【HNOI2016】—网络(树链剖分+可删堆)

    传送门

    题意:给定一棵树,支持添加一条路径,删除一条路径,询问不经过某一点的路径中的最大值

    考虑到删除和询问最大值普通线段树很难维护
    考虑把线段树上每个节点设成一个可删堆
    就可以方便的维护删除和最大值了

    由于询问“不经过某一点”的最大值,我们修改就对于整棵树关于这条路径的补集修改

    由于路径的区间是O(logn)O(logn)个,那么补集也是有O(logn)O(logn)个,排序之后依次修改就是了

    复杂度O(nlog2nloglogn)O(nlog^2nlog_{logn})

    开始总是T飞,把重儿子那里的>>改成>=就过了

    UpdateUpdate:
    LeoLeo说那是一组神仙数据,能把以11为根的链式前向星做法的loglog卡满……,需要随机剖分一下

    #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;
    }
    const int N=100005;
    int adj[N],nxt[N<<1],to[N<<1],cnt,dfn,pos[N],dep[N],n,m;
    int siz[N],fa[N],son[N],top[N];
    struct heap{
    	priority_queue<int>A,B;
    	inline void push(int x){
    		A.push(x);
    	}
    	inline void erase(int x){
    		B.push(x);
    	}
    	inline int top(){
    		while(B.size()&&A.top()==B.top())
    			A.pop(),B.pop();
    		return A.empty()?-1:A.top();
    	}
    }tr[N<<2];
    struct ask{
    	int u,v,k;
    }q[N<<1];
    pair<int,int>p[N];
    #define se second
    #define fi first
    inline void addedge(int u,int v){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    }
    void dfs1(int u){
    	siz[u]=1,son[u]=0;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==fa[u])continue;
    		fa[v]=u,dep[v]=dep[u]+1;
    		dfs1(v),siz[u]+=siz[v];
    		if(siz[v]>=siz[son[u]])son[u]=v;//就这里,别问我为什么,我也不知道
    	}
    }
    void dfs2(int u,int tp){
    	pos[u]=++dfn,top[u]=tp;
    	if(!son[u])return;
    	dfs2(son[u],tp);
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(v==son[u]||v==fa[u])continue;
    		dfs2(v,v);
    	}
    }
    #define lc (u<<1)
    #define rc ((u<<1)|1)
    #define mid ((l+r)>>1)
    inline void update(int u,int l,int r,int st,int des,int k,int op){
    	if(st<=l&&r<=des){
    		if(op)tr[u].push(k);
    		else tr[u].erase(k);
    		return;
    	}
    	if(st<=mid)update(lc,l,mid,st,des,k,op);
    	if(mid<des)update(rc,mid+1,r,st,des,k,op);
    }
    inline int query(int u,int l,int r,int pos){
    	if(l==r)return tr[u].top();
    	if(pos<=mid)return max(tr[u].top(),query(lc,l,mid,pos));
    	else return max(tr[u].top(),query(rc,mid+1,r,pos));
    }
    inline void pathupdate(int u,int v,int k,int op){
    	int tot=0;
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		p[++tot]=make_pair(pos[top[u]],pos[u]);
    		u=fa[top[u]];
    	}
    	if(dep[u]>dep[v])swap(u,v);
    	p[++tot]=make_pair(pos[u],pos[v]);
    	sort(p+1,p+tot+1);
    	p[0]=make_pair(0,0),p[tot+1]=make_pair(n+1,n+1);
    	for(int i=0;i<=tot;i++){
    		int l=p[i].se+1,r=p[i+1].fi-1;
    		if(l<=r)update(1,1,n,l,r,k,op);
    	}
    }
    int main(){
    //	freopen("lx.cpp","r",stdin);
    	n=read(),m=read();
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		addedge(u,v),addedge(v,u);
    	}
    	dfs1(1),dfs2(1,1);
    	for(int i=1;i<=m;i++){
    		int op=read();
    		switch(op){
    			case 0:{
    				q[i].u=read(),q[i].v=read(),q[i].k=read();
    				pathupdate(q[i].u,q[i].v,q[i].k,1);
    				break;
    			}
    			case 1:{
    				int p=read();
    				pathupdate(q[p].u,q[p].v,q[p].k,0);
    				break;
    			}
    			case 2:{
    				int x=read();
    				cout<<query(1,1,n,pos[x])<<'
    ';
    				break;
    			}
    		}
    	}
    }
    
  • 相关阅读:
    JNI介绍
    github自己用(未完)
    Android中的内存泄漏问题前世今生(转)
    android开发之OpenGL(三)
    android之PopupWindow焦点问题
    Spring笔记2
    android 存储ANR问题的traces.txt
    Gallery与imageView的onClick事件冲突解决方法
    android小小的开发细节
    PHP网站中整体防注入方法
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145661.html
Copyright © 2011-2022 走看看