bzoj 4538: [Hnoi2016]网络
来源:互联网 发布:中差评拦截软件 编辑:程序博客网 时间:2024/05/21 10:48
题意:
给一棵树,可以将某条路径打上/删除一个标记,询问一个点,所有打了标记的不经过该点的路径中的最大值。
题解:
一开始想到拆成两条链,dfs序一下,但好像只会维护和。
orz,发现是树链剖分+线段树套堆。
于是就可做了,树剖是将不包含的线段标记出来,在线段树上的每个点上开两个优先队列,分别表示加的值和删的值,然后两个一起pop。标记永久化。
还有些玄学地方,具体见bzoj discuss。
code:
#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct node{ int y,next;}a[200010];int len=0,last[100010];struct TRnode{ int fa,top,son,tot,dep;}TR[100010];struct trnode{ int lc,rc; priority_queue<int> q1,q2;}tr[200010];int tot=0,root=0;int ys[100010],z=0;int n,m;void ins(int x,int y){ a[++len].y=y; a[len].next=last[x];last[x]=len;}void pre_node(int x,int fa){ TR[x].dep=TR[fa].dep+1;TR[x].fa=fa;TR[x].tot=1; for(int i=last[x];i;i=a[i].next) { int y=a[i].y; if(y==fa) continue; pre_node(y,x); if(TR[TR[x].son].tot<=TR[y].tot) TR[x].son=y; TR[x].tot+=TR[y].tot; }}void pre_edge(int x,int top){ TR[x].top=top;ys[x]=++z; if(TR[x].son) pre_edge(TR[x].son,top); for(int i=last[x];i;i=a[i].next) { int y=a[i].y; if(y==TR[x].fa||y==TR[x].son) continue; pre_edge(y,y); }}struct query{ int a,b,v;}q[200010];query t[1000];int num;bool cmp(query a,query b){return a.a<b.a;}void change(int &x,int l,int r,int fl,int fr,int k,int op){ if(!x) x=++tot; if(l==fl&&r==fr) { if(op==1) tr[x].q1.push(k); else tr[x].q2.push(k); return; } int mid=(l+r)/2; if(fr<=mid) change(tr[x].lc,l,mid,fl,fr,k,op); else if(fl>mid) change(tr[x].rc,mid+1,r,fl,fr,k,op); else change(tr[x].lc,l,mid,fl,mid,k,op),change(tr[x].rc,mid+1,r,mid+1,fr,k,op);}int findans(int x,int l,int r,int k){ if(!x) return -1; while(!tr[x].q1.empty()&&!tr[x].q2.empty()&&tr[x].q1.top()==tr[x].q2.top()) tr[x].q1.pop(),tr[x].q2.pop(); int mid=(l+r)/2,K; if(tr[x].q1.empty()) K=-1; else K=tr[x].q1.top(); if(l==r) return K; if(k<=mid) return max(K,findans(tr[x].lc,l,mid,k)); return max(K,findans(tr[x].rc,mid+1,r,k));}void solve(int x,int y,int k,int op){ num=0; int tx=TR[x].top,ty=TR[y].top; while(tx!=ty) { if(TR[tx].dep<TR[ty].dep) swap(x,y),swap(tx,ty); t[++num].a=ys[tx];t[num].b=ys[x]; x=TR[tx].fa;tx=TR[x].top; } if(TR[x].dep<TR[y].dep) swap(x,y); t[++num].a=ys[y];t[num].b=ys[x]; sort(t+1,t+num+1,cmp); int p=1; for(int i=1;i<=num;i++) { if(p<t[i].a) change(root,1,n,p,t[i].a-1,k,op); p=t[i].b+1; } if(p<=n) change(root,1,n,p,n,k,op);}int main(){ scanf("%d %d",&n,&m); for(int i=1;i<n;i++) { int x,y;scanf("%d %d",&x,&y); ins(x,y);ins(y,x); } pre_node(1,0);pre_edge(1,1); for(int i=1;i<=m;i++) { int op;scanf("%d",&op); if(op==0) { scanf("%d %d %d",&q[i].a,&q[i].b,&q[i].v); solve(q[i].a,q[i].b,q[i].v,1); } if(op==1) { int t;scanf("%d",&t); solve(q[t].a,q[t].b,q[t].v,2); } if(op==2) { int x;scanf("%d",&x); printf("%d\n",findans(root,1,n,ys[x])); } }}
阅读全文
1 0
- BZOJ 4538: [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络
- BZOJ 4538 [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络 树链剖分
- 【BZOJ 4538】[Hnoi2016]网络 树链剖分+堆
- bzoj 4538: [Hnoi2016]网络 树链剖分+线段树
- [树链剖分 线段树 堆] BZOJ 4538 [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络 (整体二分+树状数组)
- 4538: [Hnoi2016]网络
- HNOI2016 网络
- HNOI2016 网络
- [HNOI2016] 网络
- BZOJ 4539: [Hnoi2016]树
- BZOJ 4542: [Hnoi2016]大数
- BZOJ 4537: [Hnoi2016]最小公倍数
- BZOJ 4541: [Hnoi2016]矿区
- bzoj 4537: [Hnoi2016]最小公倍数
- [ACM模板]AC自动机
- pyQt5搭建的简单的图像处理界面
- Android多渠道打包
- 创建maven工程use default workspace被选中的解决方法
- Layer 多按钮实现
- bzoj 4538: [Hnoi2016]网络
- 单点登陆CAS
- Java常见集合框架(十四):Queue之Queue、BlockingQueue、AbstractQueue
- Android 屏幕密度及其分辨率获取
- linux svn命令详解
- HTTP
- C++中DEELX匹配中文
- eclipse修改 f2提示框颜色
- 完全背包 Piggy-Bank HDU