来自FallDream的博客,未经允许,请勿转载,谢谢。


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

就是要支持加入/删除一条有权值的链,询问不过一个点的链的权值最大值

n<=10^5 m<=2*10^5

如果树剖的话,可以把区间取反,就等于是包含一个点的线段的权值最大值了 但是那样的话脑补一下可以发现是3个log的 还容易炸空间(我并不知道那些人是怎么过的)

然后貌似有种做法比较靠谱,就是线段树维护权值区间的所有链的交,询问时候在线段树上二分,配合O(1)的lca查询的话可以做到O(nlogn)复杂度,倍增求lca的话两个log,就已经可以过啦。

然后我的做法是直接整体二分,然后每次判断每个询问的答案大于/小于二分的值。

把大于二分值的操作都拿出来,变成整条链加/减1,询问一个点的权值。如果一个点的权值等于现在存在的链的数量,那么显然答案小等于二分值,否则答案是大于的。

链加/单点查,我们求出lca配合dfs序就变成了单点改,区间查,用线段树可以轻松实现。

复杂度nlog^2n

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define MN 200000
#define MD 17
#define N 131072
using namespace std;
inline int read()
{int x=0;char ch=getchar();while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x;
}int n,m,head[MN+5],nl[MN+5],nr[MN+5],dn,cnt,T[N*2+5],q[MN+5],q1[MN+5],q2[MN+5];
int top1,top2,fa[MD+1][MN+5],num,l[MN+5],tot=1,Ans[MN+5],dep[MN+5];
struct edge{int to,next,w;}e[MN*2+5];
struct data{int kind,x,y,z,w,ad;}s[MN+5];inline void ins(int f,int t)
{e[++cnt]=(edge){t,head[f]};head[f]=cnt;e[++cnt]=(edge){f,head[t]};head[t]=cnt;
}void Pre(int x,int f)
{nl[x]=++dn;fa[0][x]=f;for(int i=head[x];i;i=e[i].next)if(e[i].to!=f) dep[e[i].to]=dep[x]+1,Pre(e[i].to,x);nr[x]=dn;
}int lca(int x,int y)
{if(dep[x]<dep[y]) swap(x,y);for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j)if(k&1) x=fa[j][x];if(x==y) return x;for(int i=MD;~i;--i)if(fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y];return fa[0][x];
}void Modify(int x,int ad)
{T[x+=N]+=ad;for(x>>=1;x;x>>=1) T[x]=T[x<<1]+T[x<<1|1];
}int Query(int l,int r)
{int sum=0;for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1){if(~l&1) sum+=T[l+1];if( r&1) sum+=T[r-1];}return sum;
}void Solve(int l,int r,int lt,int rt)
{if(l>r) return;if(lt==rt){for(int i=l;i<=r;++i)if(s[q[i]].kind) Ans[q[i]]=lt;return;}int mid=lt+rt>>1,sum=0;top1=top2=0;for(int i=l;i<=r;++i)if(s[q[i]].kind){if(Query(nl[s[q[i]].x],nr[s[q[i]].x])==sum) q1[++top1]=q[i];else q2[++top2]=q[i];}else{if(s[q[i]].w>mid){sum+=s[q[i]].ad;Modify(nl[s[q[i]].x],s[q[i]].ad);Modify(nl[s[q[i]].y],s[q[i]].ad);Modify(nl[s[q[i]].z],-s[q[i]].ad);if(s[q[i]].z!=1) Modify(nl[fa[0][s[q[i]].z]],-s[q[i]].ad);q2[++top2]=q[i];}else q1[++top1]=q[i];}for(int i=l;i<=r;++i)if(s[q[i]].kind==0&&s[q[i]].w>mid){Modify(nl[s[q[i]].x],-s[q[i]].ad);Modify(nl[s[q[i]].y],-s[q[i]].ad);Modify(nl[s[q[i]].z],s[q[i]].ad);if(s[q[i]].z!=1) Modify(nl[fa[0][s[q[i]].z]],s[q[i]].ad);}for(int i=1;i<=top1;++i) q[l+i-1]=q1[i];for(int i=1;i<=top2;++i) q[l+top1+i-1]=q2[i];int pre=top1;Solve(l,l+top1-1,lt,mid);Solve(l+pre,r,mid+1,rt);
}int main()
{n=read();m=read();for(int i=1;i<n;++i) ins(read(),read());Pre(1,0);l[++num]=-1;for(int i=1;i<=MD;++i)for(int j=1;j<=n;++j)fa[i][j]=fa[i-1][fa[i-1][j]];for(int i=1;i<=m;++i){int op=read(); q[i]=i;if(op==0) s[i].x=read(),s[i].y=read(),s[i].z=lca(s[i].x,s[i].y),s[i].w=l[++num]=read(),s[i].ad=1;if(op==1) s[i]=s[read()],s[i].ad=-1;if(op==2) s[i].kind=1,s[i].x=read();}sort(l+1,l+num+1);for(int i=2;i<=num;++i) if(l[i]!=l[i-1]) l[++tot]=l[i];for(int i=1;i<=m;++i) if(!s[i].kind) s[i].w=lower_bound(l+1,l+tot+1,s[i].w)-l;Solve(1,m,1,tot);for(int i=1;i<=m;++i)if(s[i].kind) printf("%d\n",l[Ans[i]]);return 0;
}

转载于:https://www.cnblogs.com/FallDream/p/bzoj4538.html

[bzoj4538][Hnoi2016]网络相关推荐

  1. P3250 [HNOI2016]网络(整体二分)

    P3250 [HNOI2016]网络 给定一棵树,有三种操作: 给定u,v,wu, v, wu,v,w,表示u,vu, vu,v路径上有一个重要度为www的请求, 给定ttt,第ttt个发生的请求结束 ...

  2. P3250 [HNOI2016]网络(利用堆建线段树 + 树剖)

    P3250 [HNOI2016]网络 做法有点神奇!!!利用堆作为节点建立一颗线段树,用堆维护线段树上点的信息. 说说查询操作,我们的目的是要查询,没有经过这个点的事件最大值,考虑如何维护. 我们定义 ...

  3. [HNOI2016]网络(树链剖分+线段树+大根堆)

    [HNOI2016]网络 problem solution 另辟蹊径,不把交互请求赋在新增路径上,反而把交互请求赋在树上除去该请求路径覆盖点的其它点上 显然,路径问题树剖是非常可以的. 那么一个点上的 ...

  4. [HNOI2016]网络 树链剖分,堆

    [HNOI2016]网络 LG传送门 表示乱搞比正解难想. 整体二分很好想吧. 但是为了好写快乐,我们选择三个\(\log\)的乱搞. 先树剖,线段树套堆维护区间最大值.对于一次修改,如果是插入,就把 ...

  5. 4538: [Hnoi2016]网络

    4538: [Hnoi2016]网络 链接 分析: 整体二分. 对于一次操作,可以二分一个答案mid,判断权值大于mid的路径是否全部经过这个点.如果是 ,那么这次询问的答案在[l,mid-1]之间, ...

  6. BZOJ 4538: [Hnoi2016]网络

    这个题目就是特别裸啊,很明显就是先树链剖分,然后在线段树每个节点上维护两个堆,来维护插入和删除,查询的时候就暴力查就好了. 似乎很简单啊,我竟然在luogu上1A了,结果交到bzoj上MLE,看过讨论 ...

  7. 洛咕P3250 [HNOI2016]网络 整体二分

    这题太神仙了必须写博客... 显然可以想到二分答案.二分一个答案mid,如果所有长度\(\geq mid\)的路径都过x,那么答案一定\(<mid\),否则答案\(\geq mid\). 那么就 ...

  8. arduino 舵机接线图_用fritzing绘制arduino硬件连线图

    CCF真题之门禁系统 201412-1 问题描述 涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况.每位读者有一个编号,每条记录用读者的编号来表示.给出读者的来访记录,请问每一条记录中的读 ...

  9. # HNOI2012 ~ HNOI2018 题解

    HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...

  10. linux下sqlserver端口号,登陆sqlserver及修改端口号 (转)

    在一台计算机上面同时安装两个sql server数据库实例,第一次安装默认为机器名,端口号为1433 1.如果不知道服务器名,却想登陆的话可以直接输入127.0.0.1登陆之后,在新建查询中输入:SE ...

最新文章

  1. 127.0.0.1和0.0.0.0地址的区别
  2. 使用class-dump导出其他应用头文件
  3. HTML有几种发音模式,html – 使用lang属性和拼音发音的正确方法是什么(如果有的话)?...
  4. 如何处理win10系统内置Linux系统闪退问题
  5. Spring通过Gmail SMTP服务器MailSender发送电子邮件
  6. 边缘计算应用场景_云计算与边缘计算协同九大应用场景(2019年)发布(附PPT解读)...
  7. java数组键_Java基础之数组
  8. python 寻找数组的中心索引_Leetcode724查找数组Python的中心索引,LeetCode724,寻找,python...
  9. 设置maven的阿里云代理
  10. NDCG、AUC介绍
  11. 设计模式之GOF23代理模式03
  12. Delphi判断是否有全屏程序
  13. docker 下安装oracle
  14. java实现http/https请求
  15. MATLAB环境下基于深度学习的语音降噪方法
  16. 接收机灵敏度的计算公式推导和分析
  17. html中如何出现三重阴影,探索 CSS3 中的 box-shadow 属性
  18. AtCoder Beginner Contest 061(CD)
  19. 单元测试总结反思_考试反思,考试反思作文
  20. ABeam Recruiting | ABeam旗下艾宾信息技术开发(大连)2023届校招正式开启

热门文章

  1. python流程自动化_python selenium 自动化流程的一些总结与思考
  2. C++ tbb unsafe_erase() 并发访问 解决方案
  3. 基于springboot+vue的汽车销售系统(前后端分离)
  4. 基于SSM的图书商城
  5. java sql.setInt_java – PreparedStatement的setInt()无法在PostgreSQL上运行
  6. java基础总结06-常用api类-包装类
  7. 解决wordpress前后台非常卡的几个方法
  8. PHP 日期 加减 月数,天数,周数,小时,分,秒等等
  9. IDEA 常用设置 与 常用操作(一)
  10. Spring Framework 常用工具类一