网络 [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。
思路
【树链剖分+线段树+堆】
题意是给定一棵树,然后有若干个操作,可以新添加一条从u到v的权值为w的路径,或者将之前的一条路径删掉,动态询问不经过某个点的路径的最大权值
首先考虑先树链剖分,然后看怎么处理这三个操作
显然题目要求我们动态维护不经过一个点的最大路径权值,那么我们就考虑用堆
每个线段树的结点里面存两个堆,都是大根堆,分别维护所有的入过堆的元素和已经被删除的元素,当我们需要求堆顶元素时,只需看一下两个堆的堆顶元素是否相等,相等的话顺便同时删掉,直到找到一个不相等的或者堆为空,就返回堆顶元素。这样就可以避免了如何删除路径的尴尬问题。
接着当我们插入路径的时候,显然树链剖分沿着重链往上跳的时候可以把经过的连续路径存下来。然后我们对于这些路径取反,把取反后的路径(即跳的过程中没有经过的点集或线段集)他们的线段树的堆中加入当前需要插入路径的权值。如果是删除的话,往删除堆里加入元素就可以了。
至于查询,就是找到之后一路往上跳,然后取一个MAX就可以了(找不到返回-1)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 100005
#define lson pos<<1
#define rson pos<<1|1
using namespace std; int n,m,head[maxn],cnt=,ql,qr,qid,type,value,ans; int son[maxn],siz[maxn],fa[maxn],dep[maxn],top[maxn],id[maxn],dc; struct Save_Data{
int x,y,z;
}Q[maxn<<]; struct Edge{
int to,next;
}edge[maxn<<]; struct Seq{
int l,r;
}qry[maxn]; struct Tree{
int l,r,md;
priority_queue<int> q1,q2;
inline void push1(int x){q1.push(x);}
inline void push2(int x){q2.push(x);}
inline int top()
{
int res=-;
while(!q2.empty()&&(q2.top()==q1.top())) q1.pop(),q2.pop();
if(!q1.empty()) res=q1.top();
return res;
}
}tree[maxn<<]; inline int read(){
int x=; char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
} inline bool cmp(Seq a,Seq b)
{
return a.l<b.l;
} inline int add(int u,int v)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
} void dfs1(int u,int pa,int depth)
{
siz[u]=;fa[u]=pa;dep[u]=depth;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(v==pa) continue;
dfs1(v,u,depth+);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
} void dfs2(int u,int pa)
{
id[u]=++dc;top[u]=pa;
if(!son[u]) return;
dfs2(son[u],top[u]);
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa[u]&&v!=son[u])
{
dfs2(v,v);
}
}
} void build(int pos,int l,int r)
{
tree[pos].l=l;
tree[pos].r=r;
tree[pos].md=(l+r)>>;
if(l==r) return;
build(lson,l,tree[pos].md);
build(rson,tree[pos].md+,r);
} void update(int pos)
{
if(ql<=tree[pos].l&&tree[pos].r<=qr)
{
if(type==) tree[pos].push1(value);
else tree[pos].push2(value);
return;
}
if(ql<=tree[pos].md) update(lson);
if(tree[pos].md<qr) update(rson);
} void query(int pos)
{
ans=max(ans,tree[pos].top());
if(tree[pos].l==tree[pos].r) return;
if(qid<=tree[pos].md) query(lson);
else query(rson);
} inline void lca(int x,int y,int val)
{
int f1=top[x],f2=top[y];
int seq=;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(x,y);swap(f1,f2);
}
qry[++seq].l=id[f1];
qry[seq].r=id[x];
x=fa[f1];f1=top[x];
}
if(dep[x]<dep[y]) swap(x,y);
qry[++seq].l=id[y];qry[seq].r=id[x];
int last=;value=val;
sort(qry+,qry++seq,cmp);
for(int i=;i<=seq;++i)
{
ql=last+;qr=qry[i].l-;
if(ql<=qr) update();
last=qry[i].r;
}
ql=last+;qr=n;
if(ql<=qr) update();
} int main()
{
int a,b,c,cmd;
memset(head,-,sizeof(head));
n=read();m=read();
for(register int i=;i<n;++i)
{
a=read();b=read();
add(a,b);add(b,a);
}
dfs1(,,);
dfs2(,);
build(,,n);
for(int i=;i<=m;++i)
{
cmd=read();
if(!cmd)
{
Q[i].x=read();Q[i].y=read();Q[i].z=read();
type=;
lca(Q[i].x,Q[i].y,Q[i].z);
}
else if(cmd==)
{
a=read();
type=-;
lca(Q[a].x,Q[a].y,Q[a].z);
}
else
{
a=read();
ans=-;
qid=id[a];
query();
printf("%d\n",ans);
}
}
return ;
}
网络 [HNOI2016]的更多相关文章
- 洛谷P3250 网络 [HNOI2016] 整体二分
正解:整体二分+树状数组 解题报告: 传送门! 亲这里的建议是用整体二分呢 dbq最近看sd淘宝说话体看多了有点脑抽,,, 首先考虑如果是单组询问怎么做昂QAQ 考虑二分答案 对于所有比mid小的操作 ...
- (BZOJ4538)HNOI2016 网络
HNOI2016 Day1 T2 网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互时,数 ...
- BZOJ 4538: [Hnoi2016]网络 [整体二分]
4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...
- 「HNOI2016」网络 解题报告
「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...
- 【LG3250】[HNOI2016]网络
[LG3250][HNOI2016]网络 题面 洛谷 题解 30pts 对于\(m\leq 2000\),直接判断一下这个个点是否断掉一个交互,没断掉的里面取\(max\)即可,复杂度\(O(m^2\ ...
- 4538: [Hnoi2016]网络
4538: [Hnoi2016]网络 链接 分析: 整体二分. 对于一次操作,可以二分一个答案mid,判断权值大于mid的路径是否全部经过这个点.如果是 ,那么这次询问的答案在[l,mid-1]之间, ...
- [HNOI2016]网络 树链剖分,堆
[HNOI2016]网络 LG传送门 表示乱搞比正解难想. 整体二分很好想吧. 但是为了好写快乐,我们选择三个\(\log\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...
- 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组
[BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...
- Luogu-3250 [HNOI2016]网络
Luogu-3250 [HNOI2016]网络 题面 Luogu-3250 题解 CDQ分治...这个应该算是整体二分吧 二分重要度,按照时间从小到大加入大于重要度的边 对于一个询问,如果经过这个点的 ...
随机推荐
- 在java中获取URL的域名或IP与端口
package com.xxl.sso.sample; import java.net.URI; import java.net.URISyntaxException; public class te ...
- MyBatis - 4.动态SQL
动态 SQL是MyBatis强大特性之一.极大的简化我们拼装SQL的操作. 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似. MyBatis 采用功能强大的基于 OGNL ...
- Aho-Corasick算法实现(简单关键字过滤)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- javascript获取时间戳
时间戳: 时间戳是自 1970 年 1 月 1 日(00:00:00 GMT)以来的秒数.它也被称为 Unix 时间戳(Unix Timestamp). JavaScript 获取当前时间戳: < ...
- CentOS7中Docker-ce的卸载和安装
一.查看是否已安装了Docker软件包: #查看是否已经安装的Docker软件包sudo yum list installed | grep docker 二.如果已安装不想要的docker/dock ...
- [转]Ubuntu默认使用root用户登录并免去输入密码
启用Root用户登录 Ctrl + Alt + T进入终端, 输入cd /usr/share/lightm/ightm.conf.d, 如果提示你没有那个文件或目录.那就一次次的进入目录. 进入之后会 ...
- [转]java位运算(1)
http://blog.csdn.net/xiaochunyong/article/details/7748713 Java提供的位运算符有:左移( << ).右移( >> ) ...
- 根据关键字找进程id
#!/usr/bin/pythonimport subprocessimport sysimport loggingimport os gameproc = "jd_5.py" d ...
- zabbix_agent YUM源配置
wget http://repo.zabbix.com/zabbix/3.0/rhel/5/x86_64/zabbix-release-3.0-1.el5.noarch.rpm rpm -ivh za ...
- 向Spark集群提交任务
1.启动spark集群. 启动Hadoop集群 cd /usr/local/hadoop/ sbin/start-all.sh 启动Spark的Master节点和所有slaves节点 cd /usr/ ...