[HNOI2016] 网络

P4054[Hnoi2016 day1]网络
时间限制 : - MS   空间限制 : 165536 KB 
评测说明 : 2s
问题描述

一个简单的网络系统可以被描述成一棵无根树。每个节点为一个服务器。连接服务器与服务器的数据线则看做
一条树边。两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有服务器(包括这两个服务
器自身)。由于这条路径是唯一的,当路径上的某个服务器出现故障,无法正常运行时,数据便无法交互。此外,
每个数据交互请求都有一个重要度,越重要的请求显然需要得到越高的优先处理权。现在,你作为一个网络系统的
管理员,要监控整个系统的运行状态。系统的运行也是很简单的,在每一个时刻,只有可能出现下列三种事件中的
一种: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 


-1 

-1 







提示

分析:

      直接树链爆分+线段树(其实感觉并不算线段树,跟子节点都没什么关系)

      问题转化一下:求当前不经过这个点的路径的重要度 的最大值,动动脚趾就能发现,新增一条路径我们更新非此路径上的点即可

      线段树,每个节点两个大根堆,一个是新增的值,一个是删除的值,两堆堆顶元素相等就弹掉,询问,logn问下去,每个包含此位置的节点取堆顶,再取最大

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
template <typename T>
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<int> 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<y){
		int mid=(x+y)>>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].b<x||tree[p].a>y)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.r<B.r;
		else return A.l<B.l;
	}
};
Sec sec[100005];
void change(int x,int y,int z){
	int i,pos=0;
	tot=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		sec[++tot]=Sec(id[top[x]],id[x]);
		x=father[top[x]];
	}
	if(dep[x]>dep[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(pos<n)modify(1,pos+1,n);
}
int ans;
void query(int p,int pos){
	if(tree[p].b<pos||tree[p].a>pos)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<n;i++){
		int x,y;
		_read(x);_read(y);
		add_edge(x,y);
		add_edge(y,x);
	}
	dfs(1,0,1);
	dfs2(1,1);
	build(1,1,n);
	for(i=1;i<=m;i++){
		int op,x,y,z;
		_read(op);
		if(op==0){
			_read(x);_read(y);_read(z);
			q[i]=node(x,y,z);
			ty=1;
			change(x,y,z);
		}
		else if(op==1){
			_read(x);
			ty=2;
			change(q[x].x,q[x].y,q[x].z);
		}
		else {
			ans=-1;
			_read(x);
			query(1,id[x]);
			cout<<ans<<endl;
		}
	}
}
const int main_stack=16;  
char my_stack[128<<20];  
int main() {  
  __asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory");  
  __asm__("movl %%eax, %%esp;\n"::"a"(my_stack+sizeof(my_stack)-main_stack):"%esp");  
  main_main();  
  __asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp");  
  return 0;  
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值