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发生故障时,未被影响的请求中重要度的最大值是多少?”注意可能有某个服务器自身与自身进行数据 交互的情况。
Output
对于每个type=2的事件,即服务器出现故障的事件,输出一行一个整数,描述未被影响的请求中重要度的最大值。如果此时没有任何请求,或者所有请求均被影响,则输出-1。
树链剖分套线段树套堆维护树上区间最大值
对于修改将路径对应的区间的补集插入或删除一个值,查询对应线段树的单点查询
最坏时间复杂度O(nlog3n)
#include<cstdio> #include<queue> #include<algorithm> const int N=100005; int es[N*2],enx[N*2],e0[N],ep=2; int dep[N],sz[N],son[N],fa[N],top[N],id[N],idp=1; int n,m; void f1(int w,int pa){ fa[w]=pa; dep[w]=dep[pa]+1; sz[w]=1; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa){ f1(u,w); sz[w]+=sz[u]; if(sz[u]>sz[son[w]])son[w]=u; } } } void f2(int w,int tp){ top[w]=tp; id[w]=idp++; if(son[w])f2(son[w],tp); for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=fa[w]&&u!=son[w])f2(u,u); } } struct heap{ std::priority_queue<int>m,d; inline void ins(int x){ m.push(x); } inline void del(int x){ d.push(x); } inline int max(){ while(!d.empty()&&m.top()==d.top())m.pop(),d.pop(); if(m.empty())return -1; return m.top(); } }h[262144]; int l,r,x; void ins(int w=1,int L=1,int R=131072){ if(l<=L&&R<=r){ h[w].ins(x); return; } int M=L+R>>1; if(l<=M)ins(w<<1,L,M); if(r>M)ins(w<<1^1,M+1,R); } void del(int w=1,int L=1,int R=131072){ if(l<=L&&R<=r){ h[w].del(x); return; } int M=L+R>>1; if(l<=M)del(w<<1,L,M); if(r>M)del(w<<1^1,M+1,R); } struct sg{int l,r;}ss[64]; bool operator<(sg a,sg b){return a.l<b.l;} int sp; inline void Ins(int x,int y){ sp=0; ss[sp++]=(sg){0,0}; ss[sp++]=(sg){262145,262145}; int a=top[x],b=top[y],c; while(a!=b){ if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c; ss[sp++]=(sg){id[a],id[x]}; x=fa[a];a=top[x]; } if(dep[x]<dep[y])ss[sp++]=(sg){id[x],id[y]}; else ss[sp++]=(sg){id[y],id[x]}; std::sort(ss,ss+sp); for(int i=1;i<sp;i++)if(ss[i-1].r+1<ss[i].l){ l=ss[i-1].r+1;r=ss[i].l-1; ins(); } } inline void Del(int x,int y){ sp=0; ss[sp++]=(sg){0,0}; ss[sp++]=(sg){262145,262145}; int a=top[x],b=top[y],c; while(a!=b){ if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c; ss[sp++]=(sg){id[a],id[x]}; x=fa[a];a=top[x]; } if(dep[x]<dep[y])ss[sp++]=(sg){id[x],id[y]}; else ss[sp++]=(sg){id[y],id[x]}; std::sort(ss,ss+sp); for(int i=1;i<sp;i++)if(ss[i-1].r+1<ss[i].l){ l=ss[i-1].r+1;r=ss[i].l-1; del(); } } inline void getmax(int w){ int a=-1,b; for(w=id[w]+131071;w;w>>=1){ b=h[w].max(); if(b>a)a=b; } printf("%d\n",a); } int qa[N*2],qb[N*2],qv[N*2]; int main(){ scanf("%d%d",&n,&m); for(int i=1,a,b;i<n;i++){ scanf("%d%d",&a,&b); es[ep]=b;enx[ep]=e0[a];e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];e0[b]=ep++; } f1(1,0);f2(1,1); for(int i=1;i<=m;i++){ int op,a,b,v; scanf("%d",&op); if(op==0){ scanf("%d%d%d",&a,&b,&v); qa[i]=a;qb[i]=b;qv[i]=v; x=v; Ins(a,b); }else if(op==1){ scanf("%d",&a); x=qv[a]; Del(qa[a],qb[a]); }else{ scanf("%d",&v); getmax(v); } } return 0; }