P4054[Hnoi2016 day1]网络 | ||
|
一个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做
一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务
器自身)。由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外,
每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的
管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的
一种:1. 在某两个服务器之间出现一条新的数据交互请求;2. 某个数据交互结束请求;3. 某个服务器出现故
障。系统会在任何故障发生后立即修复。也就是在出现故障的时刻之后,这个服务器依然是正常的。但在服务器产
生故障时依然会对需要经过该服务器的数据交互请求造成影响。你的任务是在每次出现故障时,维护未被影响的请
求中重要度的最大值。注意,如果一个数据交互请求已经结束,则不将其纳入未被影响的请求范围。
第一行两个正整数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
对于每个type=2的事件,即服务器出现故障的事件,输出一行一个整数,描述未被影响的请求中重要度的最大
值。如果此时没有任何请求,或者所有请求均被影响,则输出-1。
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
-1
3
5
-1
1
-1
1
1
3
6
7
7
4
6
直接树链爆分+线段树(其实感觉并不算线段树,跟子节点都没什么关系)
问题转化一下:求当前不经过这个点的路径的重要度 的最大值,动动脚趾就能发现,新增一条路径我们更新非此路径上的点即可
线段树,每个节点两个大根堆,一个是新增的值,一个是删除的值,两堆堆顶元素相等就弹掉,询问,logn问下去,每个包含此位置的节点取堆顶,再取最大
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
template
inline void _read(T& x){
char t=getchar();bool sign=true;
while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();}
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}
int n,m,e;
int vistime;
int father[100005],size[100005],son[100005],dep[100005],id[100005],top[100005];
struct line{
int to;
line(){}
line(int y){to=y;}
};
line edge[200005];
int last[100005],_next[200005];
void add_edge(int x,int y){
edge[++e]=line(y);
_next[e]=last[x];
last[x]=e;
}
void dfs(int x,int fa,int depth){
int i,v;
int temp=0,maxson=0;
father[x]=fa;dep[x]=depth;size[x]=1;
for(i=last[x];i;i=_next[i]){
v=edge[i].to;
if(v==fa)continue;
dfs(v,x,depth+1);
size[x]+=size[v];
if(size[v]>temp){
temp=size[v];
maxson=v;
}
}
son[x]=maxson;
}
void dfs2(int x,int anc){
int i,v;
id[x]=++vistime;
top[x]=anc;
if(son[x])dfs2(son[x],anc);
for(i=last[x];i;i=_next[i]){
v=edge[i].to;
if(v!=son[x]&&v!=father[x])dfs2(v,v);
}
}
struct node{
int x,y,z;
node(){}
node(int X,int Y,int Z){x=X;y=Y;z=Z;}
};
node q[200005];
struct tree_node{
int a,b;
priority_queue q1,q2;
void push1(int x){
q1.push(x);
}
void push2(int x){
q2.push(x);
}
int top(){
while(q1.size()&&q2.size()&&q1.top()==q2.top()){
q1.pop();q2.pop();
}
if(q1.size())return q1.top();
else return -1;
}
};
tree_node tree[400005];
void build(int p,int x,int y){
tree[p].a=x;tree[p].b=y;
if(x>1;
build((p<<1),x,mid);
build((p<<1)+1,mid+1,y);
}
}
int ty,val;
void modify(int p,int x,int y){
if(tree[p].by)return;
if(tree[p].a>=x&&tree[p].b<=y){
if(ty==1)tree[p].push1(val);
else tree[p].push2(val);
return;
}
modify((p<<1),x,y);
modify((p<<1)+1,x,y);
}
int tot;
struct Sec{
int l,r;
Sec(){}
Sec(int L,int R){l=L;r=R;}
friend bool operator < (Sec A,Sec B){
if(A.l==B.l)return A.rdep[y])swap(x,y);
sec[++tot]=Sec(id[x],id[y]);
sort(sec+1,sec+1+tot);
val=z;
for(i=1;i<=tot;i++){
if(pos+1<=sec[i].l-1)modify(1,pos+1,sec[i].l-1);
pos=sec[i].r;
}
if(pospos)return;
if(tree[p].a<=pos&&tree[p].b>=pos){
ans=max(ans,tree[p].top());
}
if(tree[p].a==tree[p].b)return;
query((p<<1),pos);
query((p<<1)+1,pos);
}
int main_main(){
//freopen("temp.out","w",stdout);
int i,j,k;
cin>>n>>m;
for(i=1;i