• BZOJ4538: [Hnoi2016]网络


    Description

      一个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做
    一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务
    器自身)。由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外,
    每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的
    管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的
    一种:1.  在某两个服务器之间出现一条新的数据交互请求;2.  某个数据交互结束请求;3.  某个服务器出现故
    障。系统会在任何故障发生后立即修复。也就是在出现故障的时刻之后,这个服务器依然是正常的。但在服务器产
    生故障时依然会对需要经过该服务器的数据交互请求造成影响。你的任务是在每次出现故障时,维护未被影响的请
    求中重要度的最大值。注意,如果一个数据交互请求已经结束,则不将其纳入未被影响的请求范围。

    Input

      第一行两个正整数n,m,分别描述服务器和事件个数。服务器编号是从1开始的,因此n个服务器的编号依次是1
    ,2,3,…,n。接下来n-1行,每行两个正整数u,v,描述一条树边。u和v是服务器的编号。接下来m行,按发生时刻依
    次描述每一个事件;即第i行(i=1,2,3,…,m)描述时刻i发生的事件。每行的第一个数type描述事件类型,共3种
    类型:(1)若type=0,之后有三个正整数a,b,v,表示服务器a,b之间出现一条重要度为v的数据交互请求;(2)
    若type=1,之后有一个正整数t,表示时刻t(也就是第t个发生的事件)出现的数据交互请求结束;(3)若type=2
    ,之后有一个正整数x,表示服务器x在这一时刻出现了故障。对于每个type为2的事件,就是一次询问,即询问“
    当服务器x发生故障时,未被影响的请求中重要度的最大值是多少?”注意可能有某个服务器自身与自身进行数据
    交互的情况。2 ≤ n ≤ 10^5, 1 ≤ m ≤ 2×10^5,其他的所有输入值不超过 10^9

    Output

      对于每个type=2的事件,即服务器出现故障的事件,输出一行一个整数,描述未被影响的请求中重要度的最大
    值。如果此时没有任何请求,或者所有请求均被影响,则输出-1。

    Sample Input

    13 23
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    4 8
    4 9
    6 10
    6 11
    7 12
    7 13
    2 1
    0 8 13 3
    0 9 12 5
    2 9
    2 8
    2 2
    0 10 12 1
    2 2
    1 3
    2 7
    2 1
    0 9 5 6
    2 4
    2 5
    1 7
    0 9 12 4
    0 10 5 7
    2 1
    2 4
    2 12
    1 2
    2 5
    2 3

    Sample Output

    -1
    3
    5
    -1
    1
    -1
    1
    1
    3
    6
    7
    7
    4
    6

    HINT

    样例给出的树如下所示:



    解释其中的部分询问;下面的解释中用(a,b;t,v)表示在t时刻出现的服务器a和b之间的重

    要度为v的请求:

    对于第一个询问(在时刻1),此时没有任何请求,输出-1。

    对于第四个询问(在时刻6),此时有两条交互(8,13;2,3),(9,12;3,5),所有询问均经过2

    号服务器,输出-1。

    对于第五个询问(在时刻8),此时有三条交互(8,13;2,3),(9,12;3,5),(10,12;7,1),只有交互

    (10,12;7,1)没有经过2号服务器,因此输出其重要度1。

    对于最后一个询问(在时刻23),此时有三条交互(9,5;12,6),(9,12;16,4),(10,5;17,7)。当3

    号服务器出现故障时,只有交互(9,5;12,6)没有经过3号服务器,因此输出6。

    这道题有很多做法,我只用了感觉比较好写的一种。

    考虑整体二分,问题转化成对于每个点计算是否有不包括它的线段,容斥一下计算有多少条包含它的线段,dfs序+树状数组做做就行了。

    时间复杂度为O(Mlog^N)。

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=100010;
    const int maxm=200010;
    int n,m,first[maxn],next[maxn<<1],to[maxn<<1],e;
    void AddEdge(int u,int v) {
    	to[++e]=v;next[e]=first[u];first[u]=e;
    	to[++e]=u;next[e]=first[v];first[v]=e;	
    }
    int st[maxn],en[maxn],dep[maxn],anc[maxn][20],cnt;
    void dfs(int x,int fa) {
    	st[x]=++cnt;anc[x][0]=fa;dep[x]=dep[fa]+1;
    	rep(i,1,19) anc[x][i]=anc[anc[x][i-1]][i-1];
    	for(int i=first[x];i;i=next[i]) if(to[i]!=fa) dfs(to[i],x);
    	en[x]=cnt;
    }
    int lca(int x,int y) {
    	if(dep[x]<dep[y]) swap(x,y);
    	dwn(i,19,0) if((1<<i)<=dep[x]-dep[y]) x=anc[x][i];
    	dwn(i,19,0) if(anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i];
    	return x==y?x:anc[x][0];
    }
    int sumv[maxn],clo[maxn],T;
    void add(int x,int v) {
    	if(!x) return;
    	for(;x<=n;x+=x&-x) {
    		if(clo[x]==T) sumv[x]+=v;
    		else clo[x]=T,sumv[x]=v;
    	}
    }
    int sum(int x) {
    	int res=0;
    	for(;x;x-=x&-x) if(clo[x]==T) res+=sumv[x];
    	return res;
    }
    int ans[maxm],yes[maxm],qx[maxm],id[maxm],ty[maxm],Q[maxm];
    struct Oper {
    	int x,y,v,z;
    	int l,r;
    	bool operator < (const Oper& ths) const {return v<ths.v;}
    }A[maxm];
    struct Solver {
    	int tp,p,x,v,v2;
    	bool operator < (const Solver& ths) const {return p<ths.p;}
    }B[maxn*5];
    int tmp[maxm];
    void solve(int L,int R,int f,int h) {
    	if(f>h) return;
    	if(L+1==R) {
    		rep(i,f,h) if(ans[id[Q[i]]]>=0) ans[id[Q[i]]]=A[L].v;
    		return;
    	}
    	int mid=L+R>>1,N=0,cur=0;
    	rep(i,mid,R) {
    		B[++N]=(Solver){0,A[i].l,A[i].x,1,1};
    		B[++N]=(Solver){0,A[i].l,A[i].y,1,0};
    		B[++N]=(Solver){0,A[i].l,A[i].z,-1,0};
    		B[++N]=(Solver){0,A[i].l,anc[A[i].z][0],-1,0};
    		if(A[i].r<=m){
    			B[++N]=(Solver){0,A[i].r,A[i].x,-1,-1};
    			B[++N]=(Solver){0,A[i].r,A[i].y,-1,0};
    			B[++N]=(Solver){0,A[i].r,A[i].z,1,0};
    			B[++N]=(Solver){0,A[i].r,anc[A[i].z][0],1,0};
    		}
    	}
    	rep(i,f,h) if(ans[id[Q[i]]]>=0) B[++N]=(Solver){1,id[Q[i]],qx[Q[i]],i,0};
    	sort(B+1,B+N+1);T++;
    	rep(i,1,N) {
    		if(!B[i].tp) add(st[B[i].x],B[i].v),cur+=B[i].v2;
    		else yes[B[i].v]=!(sum(en[B[i].x])-sum(st[B[i].x]-1)==cur);
    	}
    	int l=f,r=h;
    	rep(i,f,h) {
    		if(!yes[i]) tmp[l++]=Q[i];
    		else tmp[r--]=Q[i];
    	}
    	rep(i,f,h) Q[i]=tmp[i];
    	solve(L,mid,f,r);solve(mid,R,l,h);
    }
    int main() {
    	n=read();m=read();
    	rep(i,2,n) AddEdge(read(),read());
    	int N=0,M=0,cur=0;
    	dfs(1,0);
    	rep(i,1,m) {
    		int tp=read();
    		if(!tp) {
    			N++;A[N].x=read(),A[N].y=read(),A[N].z=lca(A[N].x,A[N].y);
    			add(st[A[N].x],1);add(st[A[N].y],1);
    			add(st[A[N].z],-1);add(st[anc[A[N].z][0]],-1);
    			A[N].v=read();A[N].l=i;A[N].r=m+1;ty[i]=N;cur++;
    		}
    		else if(tp==1) {
    			int x=ty[read()];
    			A[x].r=i;
    			add(st[A[x].x],-1);add(st[A[x].y],-1);
    			add(st[A[x].z],1);add(st[anc[A[x].z][0]],1);cur--;
    		}
    		else {
    			qx[++M]=read(),id[M]=i;
    			if(sum(en[qx[M]])-sum(st[qx[M]]-1)==cur) ans[i]=-1;
    		}
    		Q[i]=i;
    	}
    	sort(A+1,A+N+1);
    	solve(1,N+1,1,M);
    	rep(i,1,M) printf("%d
    ",ans[id[i]]);
    	return 0;
    }
    

      

  • 相关阅读:
    基于模糊Choquet积分的目标检测算法
    Android开发5:布局管理器2(表格布局TableLayout)
    JAVA WEB开发环境搭建教程
    linux下自助获取帮助
    dsp下基于双循环缓冲队列的视频采集和显示记录
    找工作笔试面试那些事儿(11)---数据库知识总结(2)范式
    【Todo】Zookeeper系列文章
    VC2010对Excel的操作
    hdu2647解题报告
    premake 在64位Ubuntu系统下编译32位GCC程序
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5466287.html
Copyright © 2020-2023  润新知