传送门

据说正解是树剖套堆???然而代码看着稍微有那么一点点长……

考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$mid$

然后考虑怎么判断是否所有边都经过某一个点。我们可以用树状数组+树上差分来维护,把每一条边的两个端点的值加1,他们LCA的值减1,LCA父亲的值减1,那么如果这条边经过某一个点,那么这个点子树的和必定为1

于是我们可以把所有大于mid的边都处理出来,然后判断子树的和是否等于路径条数就行了。这个可以用dfs序+树状数组维护

然后整体二分的时候,我们还是能保证时间有序的,如果是修改,那么只有边数大于mid的修改要执行,否则直接扔到左边。询问的话,如果子树和等于大于mid的边数,就扔进左边,否则扔进右边

然后代码里是每一次修改的时候都求一遍LCA的,所以时间复杂度是$O(n\ log^2n)$,如果用ST表求LCA的话应该能再减掉一个$log$

 //minamoto
#include<bits/stdc++.h>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int K=-,Z;
inline void Ot(){fwrite(sr,,K+,stdout),K=-;}
inline void print(int x){
if(K><<)Ot();if(x<)sr[++K]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++K]=z[Z],--Z);sr[++K]='\n';
}
const int N=2e5+;
int head[N],Next[N],ver[N],tot;
inline void add_edge(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
struct node{
int op,x,t,ans;
inline bool operator <(const node &b)const
{return t<b.t;}
}q[N],ll[N],rr[N];
int n,m,num,c[N],fa[N],top[N],sz[N],son[N],ls[N],rs[N],dep[N],cnt,mx;
int A[N],B[N],C[N],ans[N];
inline void add(int x,int y){for(;x<=n;x+=x&-x)c[x]+=y;}
inline int query(int x){
int res=;
for(;x;x-=x&-x) res+=c[x];
return res;
}
inline int query(int l,int r){return query(r)-query(l-);}
void dfs1(int u){
sz[u]=,dep[u]=dep[fa[u]]+,ls[u]=++cnt;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]){
fa[v]=u,dfs1(v),sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
rs[u]=cnt;
}
void dfs2(int u,int t){
top[u]=t;
if(son[u]){
dfs2(son[u],t);
for(int i=head[u];i;i=Next[i])
if(ver[i]!=fa[u]&&ver[i]!=son[u])
dfs2(ver[i],ver[i]);
}
}
inline int LCA(int u,int v){
while(top[u]!=top[v])
dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
return dep[u]<dep[v]?u:v;
}
void update(int u,int v,int x){
int lca=LCA(u,v);
add(ls[u],x),add(ls[v],x),add(ls[lca],-x);
if(fa[lca]) add(ls[fa[lca]],-x);
}
void solve(int l,int r,int ql,int qr){
if(l==r){for(int i=ql;i<=qr;++i) if(q[i].op==) q[i].ans=l;return;}
int mid=(l+r)>>,path=,cl=,cr=;
for(int i=ql;i<=qr;++i){
if(q[i].op==){
if(query(ls[q[i].x],rs[q[i].x])==path) ll[++cl]=q[i];
else rr[++cr]=q[i];
}else{
if(C[q[i].x]<=mid) ll[++cl]=q[i];
else{
int x=q[i].op?-:;path+=x;
update(A[q[i].x],B[q[i].x],x);
rr[++cr]=q[i];
}
}
}
for(int i=;i<=cr;++i) if(rr[i].op!=){
int x=rr[i].op?:-;
update(A[rr[i].x],B[rr[i].x],x);
}
for(int i=;i<=cl;++i) q[ql+i-]=ll[i];
for(int i=;i<=cr;++i) q[ql+cl+i-]=rr[i];
if(cl) solve(l,mid,ql,ql+cl-);
if(cr) solve(mid+,r,ql+cl,qr);
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=,u,v;i<n;++i)
u=read(),v=read(),add_edge(u,v),add_edge(v,u);
dfs1(),dfs2(,);
for(int i=;i<=m;++i){
q[i].op=read(),q[i].t=i;
if(!q[i].op){
A[i]=read(),B[i]=read(),C[i]=read();
q[i].x=i,cmax(mx,C[i]);
}else q[i].x=read();
}
solve(-,mx,,m);
sort(q+,q++m);
for(int i=;i<=m;++i)
if(q[i].op==) print(q[i].ans);
Ot();
return ;
}

洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)的更多相关文章

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

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

  2. [洛谷P3250][HNOI2016]网络

    题目大意:给定一棵树.有三种操作: $0\;u\;v\;t:$在$u$到$v$的链上进行重要度为$t$的数据传输. $1\;x:$结束第$x$个数据传输. $2\;x:$询问不经过点$x$的数据传输中 ...

  3. 【BZOJ4538】[Hnoi2016]网络 整体二分+树状数组

    [BZOJ4538][Hnoi2016]网络 Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做一条树边.两个服务器进行数据的交互 ...

  4. BZOJ 4538: [Hnoi2016]网络 [整体二分]

    4538: [Hnoi2016]网络 题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值 考虑二分 整体二分最大权值,如果\(k \in [mid+1, ...

  5. 洛谷P3527 MET-Meteors [POI2011] 整体二分

    正解:整体二分 解题报告: 传送门! 还有个双倍经验!(明明是一样的题目为什么你们一个紫一个黑啊喂! 这题首先要想到可以二分嘛,然后看到多组询问肯定就整体二分鸭 那就是基本套路啊,发现是区间修改单点查 ...

  6. UOJ#291. 【ZJOI2017】树状数组 树套树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ291.html 题解 结论:这个写错的树状数组支持的是后缀加和后缀求和.这里的后缀求和在 x = 0 的时 ...

  7. POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权

    题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作: 0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置 1 x val   把第 x 条边的权值改为 ...

  8. 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)

    [BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...

  9. 模拟赛 T3 DFS序+树状数组+树链的并+点权/边权技巧

    题意:给定一颗树,有 $m$ 次操作. 操作 0 :向集合 $S$ 中加入一条路径 $(p,q)$,权值为 $v$ 操作 1 :给定一个点集 $T$,求 $T$ 的并集与 $S$ 中路径含交集的权和. ...

随机推荐

  1. python学习之-- logging模块

    logging模块功能:提供了标准的日志接口,可以通过它存储各种格式的日志.日志5个级别分:debug(),info(),warning(),error(),critical() logging.ba ...

  2. 洛谷 P3811 【模板】乘法逆元

    P3811 [模板]乘法逆元 题目背景 这是一道模板题 题目描述 给定n,p求1~n中所有整数在模p意义下的乘法逆元. 输入输出格式 输入格式: 一行n,p 输出格式: n行,第i行表示i在模p意义下 ...

  3. canvas仿芝麻信用分仪表盘

    这是一个仿支付宝芝麻信用分的一个canvas,其实就是一个动画仪表盘. 首先, 上原图: 这个是在下支付宝上的截图,分低各位见笑了.然后看下我用canvas实现的效果图: <canvas id= ...

  4. 在Studio中使用Access数据库时,提示“未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序”

    错误提示:

  5. 《从0到1》读书笔记第一章&quot;未来的挑战&quot;第1记:把握潮流风向

    这几天刚到手当前炙手可热的来自PayPal创始人Peter Thiel的<Zero to One>.中文名<从0到1>,由高玉芳翻译.中信出版社出版.由于到货时刚好有事情在忙, ...

  6. B-Tree 索引和 Hash 索引的对照

    对于 B-tree 和 hash 数据结构的理解可以有助于预測不同存储引擎下使用不同索引的查询性能的差异.尤其是那些同意你选择 B-tree 或者 hash 索引的内存存储引擎. B-Tree 索引的 ...

  7. fedora下安装xdot和objgraph

    前提:安装好了python 1.先下载xdot-0.6.tar.gz和objgraph-1.8.0-py27-none-any.whl,你也可以在官网上下载其他版本. 2.下载完后,解压. 3.打开终 ...

  8. 【转】LoadRunner监控 -- Linux的17个指标

    这17个指标根据需要设置,指标设置的越多,对服务器真实值影响越大,所以要秉承按需而设的原则.   1.Average load:Average number of processes simultan ...

  9. 启动两个Tomcat的方法

     由于项目需要,所以要启动两个工程,但是又不能用一个Tomcat,于是就琢磨起了怎么启动两个Tomcat 1:首先,conf/server.xml要把HTTP的端口改成不一致的,我一个是8088,一个 ...

  10. oracle sql 超长报ORA-01460错误

    程序查找数据的时候报错了: ORA-01460: 转换请求无法实施或不合理 这是什么鬼?不合理你就提嘛,报错干什么. 程序原本好好的,现在突然报错了.数据库并没有什么更改. 后来猜测是因为执行的SQL ...