[POJ3237]树的维护
来源:互联网 发布:360解压缩软件 编辑:程序博客网 时间:2024/05/07 17:32
给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。
冲着树链剖分来的,结果发现自己太弱了操作二的标记不会打,YY了2个多小时才写完QAQ
注意全部操作均为边权,于是要将边权下放到点上,具体看代码
#include<map>#include<set>#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int maxn=210000+10;struct seg{ int l,r,delta; seg *lc,*rc; int mx,mi; seg():mx(0),mi(0),delta(0){}};seg *root=new seg;int Belong[maxn],deep[maxn],size[maxn];struct edge{ int to,next,w,f;}G[maxn*5];int n,m,q,tot=0,h[maxn];int fa[maxn][16],pos[maxn];int ans,ind=0;bool vis[maxn];int X[maxn],Y[maxn],Z[maxn];char ch;int read(){ int num=0; ch=getchar(); while (ch<'!') ch=getchar(); while (ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();} return num;}void add(int x,int y,int z){ ++tot; G[tot].to=y; G[tot].w=z; G[tot].next=h[x]; h[x]=tot;}void DFS1(int x,int dep){ deep[x]=dep; size[x]=1; vis[x]=1; for (int i=1;i<=15;++i){ if (deep[x]<(1<<i)) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for (int i=h[x];i;i=G[i].next){ int v=G[i].to; if (vis[v]) continue; fa[v][0]=x; DFS1(v,dep+1); size[x]+=size[v]; }}void DFS2(int x,int L){ int k=0; ++ind; pos[x]=ind; Belong[x]=L; for (int i=h[x];i;i=G[i].next) if (deep[x]<deep[G[i].to]&&size[G[i].to]>size[k]) k=G[i].to; if (!k) return ; DFS2(k,L); for (int i=h[x];i;i=G[i].next) if (deep[x]<deep[G[i].to]&&k!=G[i].to) DFS2(G[i].to,G[i].to);}void build(seg *p,int l,int r){ p->l=l; p->r=r; if (l+1==r) return; else if (l+1<r){ int mid=(l+r)>>1; p->lc=new seg; p->rc=new seg; if (l<mid) build(p->lc,l,mid); if (mid<r) build(p->rc,mid,r); }}void updatemax(seg *p){//带懒标记的更新要谨慎…… if (p->l+1==p->r) return; if (p->lc) p->mx=p->lc->mx; else{ if (p->rc) p->mx=p->rc->mx; return; } if (p->rc) p->mx=max(p->mx,p->rc->mx);}void updatemin(seg *p){ if (p->l+1==p->r) return; if (p->lc) p->mi=p->lc->mi; else{ if (p->rc) p->mi=p->rc->mi; return; } if (p->rc) p->mi=min(p->mi,p->rc->mi);}void Swap(seg *p){ int t=p->mx; p->mx=-p->mi; p->mi=-t;}void push_down(seg *p){//注意标记的写法,更新儿子的值 if (!p->delta) return; else{ p->delta=0; if (p->l+1==p->r) return; if (p->lc) p->lc->delta^=1; if (p->rc) p->rc->delta^=1; if (p->lc) Swap(p->lc); if (p->rc) Swap(p->rc); }}void update(seg *p,int pos,int val){ if (p->l+1==p->r){p->mx=p->mi=val;return ;} else{ int mid=(p->l+p->r)>>1; if (p->delta) push_down(p); if (pos<mid) update(p->lc,pos,val); if (mid<=pos) update(p->rc,pos,val); updatemax(p); updatemin(p); }}void Qmax(seg *p,int l,int r){//对于这道题要改就改到底,否则会影响程序正确性 if (l<=p->l&&p->r<=r){ push_down(p); if (p->l+1==p->r){ ans=max(ans,p->mx); return; } if (p->lc) Qmax(p->lc,l,r); if (p->rc) Qmax(p->rc,l,r); updatemax(p); updatemin(p); ans=max(ans,p->mx); }else{ push_down(p); if (p->l+1==p->r) return; int mid=(p->l+p->r)>>1; if (l<mid) Qmax(p->lc,l,r); if (mid<r) Qmax(p->rc,l,r); updatemax(p); updatemin(p); }}void change(seg *p,int l,int r){ if (l<=p->l&&p->r<=r){ p->delta^=1; if (p->l+1==p->r){Swap(p);} return;} else{ if (p->delta) push_down(p); int mid=(p->l+p->r)>>1; if (l<mid) change(p->lc,l,r); if (mid<r) change(p->rc,l,r); updatemax(p); updatemin(p); }}int solve(int u,int v){ int sum=-100000000; bool flag=0; if (u==9) flag=1; while (Belong[u]!=Belong[v]){ ans=-100000000; Qmax(root,pos[Belong[u]],pos[u]+1); sum=max(sum,ans); u=fa[Belong[u]][0]; } ans=-100000000; Qmax(root,pos[v]+1,pos[u]+1);//注意这里的pos[v]+1 sum=max(sum,ans); return sum;}int LCA(int a,int b){ if (deep[a]<deep[b]) swap(a,b); int t=deep[a]-deep[b]; for (int i=0;i<=15;++i) if (t&(1<<i)) a=fa[a][i]; for (int i=15;~i;i--) if (fa[a][i]!=fa[b][i]){ a=fa[a][i];b=fa[b][i];} if (a==b) return a; else return fa[a][0];}void Fchange(int u,int v){ while (Belong[u]!=Belong[v]){ change(root,pos[Belong[u]],pos[u]+1); u=fa[Belong[u]][0]; if (u==0) return; } change(root,pos[v]+1,pos[u]+1);}int main(){ freopen("maintaintree.in","r",stdin); freopen("maintaintree.out","w",stdout); n=read(); for (int i=1;i<n;++i){ int x,y,z; x=read(); y=read(); z=read(); add(x,y,z); add(y,x,z); X[i]=x; Y[i]=y; Z[i]=z; } DFS1(1,1); DFS2(1,1); build(root,1,ind+1); update(root,pos[1],-100000000); for (int i=1;i<n;++i){ int u=X[i],v=Y[i],w=Z[i]; if (deep[u]<deep[v]) swap(u,v); update(root,pos[u],w); } char ch[10]; int x,y; while (scanf("%s",ch)==1){ if (ch[0]=='D') break; x=read(); y=read(); if (ch[0]=='C'){//边权下放到深儿子上 int a=X[x],b=Y[x],Aim; if(deep[a]>deep[b])Aim=a;else Aim=b; Z[Aim]=y; update(root,pos[Aim],y); }else if (ch[0]=='N'){ int zx=LCA(x,y); Fchange(x,zx); Fchange(y,zx); }else{ int zx=LCA(x,y); printf("%d\n",max(solve(x,zx),solve(y,zx))); } } //碉堡啦!}
1 0
- [POJ3237]树的维护
- [POJ3237]树的维护
- poj3237(树链剖分边维护+线段树区间更新)
- 【动态树】poj3237
- POJ3237 树链剖分+线段树
- poj3237--Tree(树链剖分+线段树)
- 树链剖分+线段树 poj3237 Tree
- poj3237 树链部分 边权模板
- 【POJ3237】Tree(树链剖分+线段树(基于边权))
- 树链剖分+线段树 POJ3237 权值在边 模板
- poj3237 树链剖分
- poj3237 树链剖分
- poj3237 Tree
- 树链剖分 POJ3237
- 【poj3237】 Tree
- poj3237 Tree
- poj3237 树链剖分
- POJ3237:Tree
- The ClassFile Structure
- outs.write(baos.toByteArray()) 内存溢出
- php库文件加载问题
- 原生二维码的生成
- 使用leangoo实现多泳道任务看板
- [POJ3237]树的维护
- mysql新建用户无法登录解决方案
- static关键字小结
- iOS开发之-- DNS解析(网络切换的问题解决)
- Activity生命周期
- 欢迎使用CSDN-markdown编辑器
- python之爬虫框架
- 近期已完成及需要完成的工作
- swftools工具将pdf文件转换为swf文件