zoukankan      html  css  js  c++  java
  • [HNOI 2016] 网络

    题目

    传送门

    解法

    题目询问未被影响的请求中重要度的最大值,不如将其简单化,二分最大值再检验其是否受影响。

    关于二分值 ( m mid),容易想到求出所有权值为 ( m mid) 的路径的交,如果交包含故障点则受影响。求路径的交有一个小 ( ext{trick}):对于两条路径 ((x,y),(z,w)),求出 ( ext{lca}(x,z), ext{lca}(x,w), ext{lca}(y,z), ext{lca}(y,w)) 并找出最深的两点 (a,b),若

    1. (a eq b)。路径的交为 ((a,b))
    2. (a=b)。若 (a) 为某条路径的 ( m lca),路径的交为 (a);反之没有。

    这样就可以在权值线段树上二分。需要维护 ((s,t,tag)),其中 (s,t) 为路径交,(tag) 为是否有路径。

    需要注意的是,权值可能相同,我们需要将权值离散化使其互异。因为别忘了还有删除操作,如果将权值相同的路径直接合并在叶子节点就会导致无法分离。

    ( m lca)rmq 就可以做到 (mathcal O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
    #define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
    #define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
    #define print(x,y) write(x),putchar(y) 
    #define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
    template <typename T> void Out(T x) {cerr<<x<<"
    ";}
    template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}
    
    template <class T> inline T read(const T sample) {
        T x=0; int f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    template <class T> inline void write(const T x) {
        if(x<0) return (void) (putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    const int maxn=1e5+5,maxm=2e5+5;
    
    int n,m,ou[maxn<<1],id[maxn];
    int dep[maxn],cnt,st[maxn<<1][21];
    int lg[maxn<<1],p[maxm],num,rk[maxm];
    
    // why is maxm?
    
    vector <int> e[maxn];
    struct Query {
    	int opt,a,b,c;
    } q[maxm];
    struct Tree {
    	int u,v; bool tag;
    } t[maxm<<2];
    
    void dfs(int u,int fa) {
    	dep[u]=dep[fa]+1,ou[++cnt]=u;
    	id[u]=cnt;
    	for(int i=0;i<e[u].size();++i) {
    		int v=e[u][i];
    		if(v==fa) continue;
    		dfs(v,u);
    		ou[++cnt]=u;
    	}
    }
    
    void init() {
    	rep(i,1,cnt) st[i][0]=ou[i];
    	lg[1]=0;
    	rep(i,2,cnt) lg[i]=lg[i>>1]+1;
    	rep(j,1,19) {
    		rep(i,1,cnt)
    			if(i+(1<<j)-1<=cnt) {
    				if(dep[st[i][j-1]]<dep[st[i+(1<<j-1)][j-1]])
    					st[i][j]=st[i][j-1];
    				else st[i][j]=st[i+(1<<j-1)][j-1];
    			}
    	}
    }
    
    int lca(int l,int r) {
    	l=id[l],r=id[r];
    	if(l>r) swap(l,r);
    	// important!!!
    	int d=lg[r-l+1];
    	if(dep[st[l][d]]<dep[st[r-(1<<d)+1][d]])
    		return st[l][d];
    	return st[r-(1<<d)+1][d];
    }
    
    bool cmp(int a,int b) {
    	return q[a].c<q[b].c;
    }
    
    bool cmpd(int a,int b) {
    	return dep[a]>dep[b];
    }
    
    void pushUp(int o) {
    	if(!o) return;
    	int ls=o<<1,rs=o<<1|1;
    	static int lc[5];
    	t[o].tag=1;
    	if((t[ls].tag|t[rs].tag)==0)
    		t[o].tag=0;
    		// 没有路径
    	else if(!t[rs].tag)
    		t[o].u=t[ls].u,
    		t[o].v=t[ls].v;
    	else if(!t[ls].tag)
    		t[o].u=t[rs].u,
    		t[o].v=t[rs].v;
    	else {
    		lc[1]=lca(t[ls].u,t[rs].u);
    		lc[2]=lca(t[ls].u,t[rs].v);
    		lc[3]=lca(t[ls].v,t[rs].u);
    		lc[4]=lca(t[ls].v,t[rs].v);
    		sort(lc+1,lc+5,cmpd);
    		if(lc[1]^lc[2]) t[o].u=lc[1],t[o].v=lc[2];
    		else if(lc[1]==lca(t[ls].u,t[ls].v) or
    				lc[1]==lca(t[rs].u,t[rs].v))
    					t[o].u=t[o].v=lc[1];
    		else t[o].u=t[o].v=0;
    		// 没有路径的交
    	}
    }
    
    void modify(int o,int l,int r,int pos,int x,int y) {
    	if(l>pos or r<pos) return;
    	if(l==r) return (void)(t[o].u=x,t[o].v=y,t[o].tag=1);
    	int mid=l+r>>1;
    	modify(o<<1,l,mid,pos,x,y),modify(o<<1|1,mid+1,r,pos,x,y); 
    	pushUp(o);
    }
    
    void del(int o,int l,int r,int pos) {
    	if(l>pos or r<pos) return;
    	if(l==r) return (void)(t[o].u=t[o].v=t[o].tag=0);
    	int mid=l+r>>1;
    	del(o<<1,l,mid,pos),del(o<<1|1,mid+1,r,pos);
    	pushUp(o);
    }
    
    bool In(int u,int v,int x) {
    	if(!u and !v) return 0;
    	int Lca=lca(u,v);
    	if(lca(Lca,x)^Lca) return 0;
    	if(lca(u,x)!=x and lca(v,x)!=x) return 0;
    	return 1;
    }
    
    int query(int o,int l,int r,int er) {
    	if(!t[o].tag) return -1;
    	while(l^r) {
    		int mid=l+r>>1;
    		if(t[o<<1|1].tag and 
    			!In(t[o<<1|1].u,t[o<<1|1].v,er)) {
    		   	l=mid+1; o=o<<1|1;
    		}
    		else {
    			r=mid; o<<=1;
    		}
    	}
    	if(!t[o].tag or In(t[o].u,t[o].v,er))
    		return -1;
    	return l;
    }
    
    int main() {
    	n=read(9),m=read(9);
    	rep(i,1,n-1) {
    		int u=read(9),v=read(9);
    		e[u].push_back(v);
    		e[v].push_back(u);
    	}
    	dfs(1,0),init();
    	rep(i,1,m) {
    		q[i].opt=read(9),q[i].a=read(9);
    		if(!q[i].opt) {
    			q[i].b=read(9),q[i].c=read(9);
    			p[++num]=i;
    		}
    	}
    	sort(p+1,p+num+1,cmp);
    	rep(i,1,num) rk[p[i]]=i;
    	rep(i,1,m) {
    		if(!q[i].opt) {
    			modify(1,1,num,rk[i],q[i].a,q[i].b);
    		}
    		else if(q[i].opt==1) {
    			del(1,1,num,rk[q[i].a]);
    		}
    		else {
    			int ans=query(1,1,num,q[i].a);
    			print(ans==-1?-1:q[p[ans]].c,'
    ');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Django开发个人博客网站
    Photoshop界面字体太小解决方案
    [Leetcode]第三题:无重复字符最长子串
    web网站服务(1)
    备份与恢复笔记和实验
    oracle事物和常用数据库对象笔记和实验
    Oracle配置管理实验
    Oracle配置管理笔记
    Oracle体系结构和用户管理实验
    Oracle数据库部署
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15012793.html
Copyright © 2011-2022 走看看