bzoj4538: [Hnoi2016]网络
来源:互联网 发布:哈登职业生涯数据预测 编辑:程序博客网 时间:2024/06/14 16:09
传送门
本来想用树剖艹,然而并不会卡常数这种神奇的技能,,,于是还是乖乖写正解吧QAQ
我们可以把一个询问转化为二分判定性问题
二分答案K
,若所有权值大于K的路径都经过询问点x,则答案比K小,否则答案比K大
对于多组询问,外层再套一个整体二分就行了
至于判断有几条路径经过点x
,对于一条路径(u,v)我们把u和v置为1,lca(u,v)和lca(u,v)的父亲置为−1,这样经过一个节点x
的路径条数就是以其为根的子树的标记和,,,
由于子树区间求和有关,于是可以用dfs序维护
然后可以O(1)
求lca,即通过欧拉回路把lca转化为rmq问题。
#include<cmath> #include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define fi first#define se second#define N 100005using namespace std;pair<int,int> pos[N];struct data{int op,id,x,ans;}q[N*2],tmp[N*2];struct edge{int to,next;}e[N*2];int head[N],st[N*4][20],log_2[N*2],vis[N];int dep[N],A[N*2],B[N*2],C[N*2],bit[N],fa[N];int tot,ss,n,m,x,y,tim,mx;bool cmp(data x,data y){ return x.id<y.id;}void add(int x,int y){ e[++tot]=(edge){y,head[x]}; head[x]=tot; e[++tot]=(edge){x,head[y]}; head[y]=tot; }void dfs(int x){ pos[x].fi=++tim; st[++ss][0]=x; vis[x]=ss; for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]){ fa[e[i].to]=x; dep[e[i].to]=dep[x]+1; dfs(e[i].to); st[++ss][0]=x; } pos[x].se=tim;}int Min(int x,int y){ return dep[x]<dep[y]?x:y; }void build(){ for (int i=2;i<=ss;i++) log_2[i]=log_2[i>>1]+1; for (int j=1;j<=log_2[ss];j++) for (int i=1;i<=ss;i++) st[i][j]=Min(st[i][j-1],st[i+(1<<(j-1))][j-1]);}int lca(int x,int y){ x=vis[x]; y=vis[y]; if (x>y) swap(x,y); int len=log_2[y-x+1]; return Min(st[x][len],st[y-(1<<len)+1][len]);}void change(int x,int v){ for (;x<=n;x+=x&(-x)) bit[x]+=v;}int ask(int x){ int s=0; for (;x;x-=x&(-x)) s+=bit[x]; return s;}void update(int x,int y,int op){ int _lca=lca(x,y); change(pos[x].fi,op); change(pos[y].fi,op); change(pos[_lca].fi,-op); if (fa[_lca]) change(pos[fa[_lca]].fi,-op);}int query(int x){ return ask(pos[x].se)-ask(pos[x].fi-1);}void erfen(int L,int R,int l,int r){ if (L>R) return; int mid=(l+r)>>1; if (l==r){ for (int i=L;i<=R;i++) if (q[i].op==2) q[i].ans=mid; return; } int qq=L-1,tt=0,num=0; for (int i=L;i<=R;i++) if (q[i].op==2){ if (query(q[i].x)==num) q[++qq]=q[i]; else tmp[++tt]=q[i]; } else{ int op=q[i].op?-1:1; if (C[q[i].x]<=mid) q[++qq]=q[i]; else{ tmp[++tt]=q[i]; num+=op; update(A[q[i].x],B[q[i].x],op); } } for (int i=1;i<=tt;i++) if (tmp[i].op!=2){ int op=tmp[i].op?1:-1; update(A[tmp[i].x],B[tmp[i].x],op); } for (int i=1;i<=tt;i++) q[qq+i]=tmp[i]; erfen(L,qq,l,mid); erfen(qq+1,qq+tt,mid+1,r);}int main(){ //freopen("1.in","r",stdin); scanf("%d%d",&n,&m); for (int i=1;i<n;++i){ scanf("%d%d",&x,&y); add(x,y); } dfs(1); build(); for (int i=1;i<=m;i++){ scanf("%d",&q[i].op); q[i].id=i; if (q[i].op==0){ scanf("%d%d%d",&A[i],&B[i],&C[i]); q[i].x=i; mx=max(mx,C[i]); } else scanf("%d",&q[i].x); } erfen(1,m,-1,mx); sort(q+1,q+m+1,cmp); for (int i=1;i<=m;i++) if (q[i].op==2) printf("%d\n",q[i].ans);}
0 0
- BZOJ4538: [Hnoi2016]网络
- BZOJ4538 HNOI2016 网络
- bzoj4538: [Hnoi2016]网络
- bzoj4538: [Hnoi2016]网络
- [bzoj4538][Hnoi2016]网络
- bzoj4538【HNOI2016】网络
- bzoj4538: [HNOI2016]网络
- bzoj4538: [Hnoi2016]网络
- 【BZOJ4538】【HNOI2016】网络
- Bzoj4538:[Hnoi2016]网络:整体二分+树状数组
- 【bzoj4538】【HNOI2016】【网络】【树链剖分+线段树套堆】
- [BZOJ4538]网络
- BZOJ4538:[Hnoi2016]网络 (整体二分+Lca+树状数组/线段树+路径交/树链剖分+Heap)
- BZOJ4538 网络 [树链剖分]
- HNOI2016 网络
- HNOI2016 网络
- [HNOI2016] 网络
- BZOJ 4538: [Hnoi2016]网络
- 语言基础
- ZOJ2836 容斥原理
- 欢迎使用CSDN-markdown编辑器
- android-vlc W/VLC: yuv_rgb_neon filter: can't get output picture
- 系统的简单注解
- bzoj4538: [Hnoi2016]网络
- C++上机实验4-项目6
- 谷歌浏览器中微场景swiper中swipeUp无效问题
- noip提高组2011 mayan游戏
- 程序调试方法总结
- C++第4次实验 【项目6:输出星号图】
- 数据分析师应该干些什么
- 同余定理
- C++第四次实验报告