树链剖分 POJ3237
来源:互联网 发布:pdg for mac 编辑:程序博客网 时间:2024/05/19 22:27
树链剖分
对于静态树的点权或边权的修改查询问题,都可以用轻重链剖分解决
有关树上询问的问题可以参考Orz杨哲神犇
模板题:POJ3237
个人代码:
#include<iostream>#include<cstdio>#include<cstring>#define lc o<<1#define rc o<<1|1using namespace std;const int N=10000+5;const int inf=1e9;struct Node{ int l,r,mx,mi; bool mark;}tr[N*4];struct Edge{int to,next,v;}e[N*3];int fa[N],dep[N],son[N],siz[N],pos[N],top[N],cnt,node,val[N],rank[N],head[N];void ins(int u,int v,int w){ cnt++;e[cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;}void dfs1(int u){ siz[u]=1;son[u]=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==fa[u])continue; fa[v]=u; dep[v]=dep[u]+1; val[v]=e[i].v; dfs1(v); siz[u]+=siz[v]; if(siz[v]>siz[son[u]])son[u]=v; }}void dfs2(int u,int tp){ pos[u]=++node;top[u]=tp;rank[node]=u; if(son[u])dfs2(son[u],top[u]); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); }}inline void pushup(int o){ tr[o].mx=max(tr[lc].mx,tr[rc].mx); tr[o].mi=min(tr[lc].mi,tr[rc].mi);}inline void pushdown(int o){ if(tr[o].mark){ swap(tr[lc].mi,tr[lc].mx);tr[lc].mi*=-1;tr[lc].mx*=-1; swap(tr[rc].mi,tr[rc].mx);tr[rc].mi*=-1;tr[rc].mx*=-1; tr[lc].mark^=1;tr[rc].mark^=1; tr[o].mark^=1; }}void build(int o,int l,int r){ tr[o].l=l;tr[o].r=r;tr[o].mark=false; if(l==r){ tr[o].mi=tr[o].mx=val[rank[l]]; }else{ int m=l+r>>1; build(lc,l,m);build(rc,m+1,r); pushup(o); }}void update(int o,int p,int v){ int l=tr[o].l,r=tr[o].r; if(l==r)tr[o].mx=tr[o].mi=v; else{ pushdown(o); int m=l+r>>1; if(p<=m)update(lc,p,v); else update(rc,p,v); pushup(o); }}void anti(int o,int a,int b){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r){ tr[o].mark^=1; swap(tr[o].mi,tr[o].mx);tr[o].mi*=-1;tr[o].mx*=-1; }else{ pushdown(o); int m=l+r>>1; if(b<=m)anti(lc,a,b); else if(m<a)anti(rc,a,b); else{anti(lc,a,m);anti(rc,m+1,b);} pushup(o); }}int query(int o,int a,int b){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].mx; else{ pushdown(o); int m=l+r>>1; if(b<=m)return query(lc,a,b); else if(m<a)return query(rc,a,b); else return max(query(lc,a,m),query(rc,m+1,b)); }}void change(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); anti(1,pos[top[u]],pos[u]); u=fa[top[u]]; } if(u==v)return; if(dep[u]>dep[v])swap(u,v); anti(1,pos[son[u]],pos[v]);}int ask(int u,int v){ int ans=-inf; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans=max(ans,query(1,pos[top[u]],pos[u])); u=fa[top[u]]; } if(u==v)return ans; if(dep[u]>dep[v])swap(u,v); return max(ans,query(1,pos[son[u]],pos[v]));}int main(){ //freopen("a.in","r",stdin); int T;scanf("%d",&T); while(T--){ int n;scanf("%d",&n);int u,v,w; cnt=0;node=0;memset(head,0,sizeof(head)); for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&w); ins(u,v,w);ins(v,u,w); } dfs1(1);dfs2(1,1); build(1,1,n); char opt[10];int a,b; while(true){ scanf("%s",opt); if(opt[0]=='D')break; scanf("%d%d",&a,&b); if(opt[0]=='C'){ u=e[a*2].to;v=e[a*2-1].to; if(dep[u]<dep[v])swap(u,v); update(1,pos[u],b); }else if(opt[0]=='Q'){ printf("%d\n",ask(a,b)); }else{ change(a,b); } } } return 0;}
0 0
- poj3237 树链剖分
- poj3237 树链剖分
- 树链剖分 POJ3237
- poj3237 树链剖分
- POJ3237树链剖分
- POJ3237 树链剖分+线段树
- 【POJ3237】Tree 树链剖分
- poj3237 Tree 树链剖分
- poj3237 Tree [树链剖分]
- 【POJ3237】Tree(树链剖分)
- 【POJ3237】Tree-树链剖分
- poj3237(树链剖分—边权)
- POJ3237 Tree【树链剖分】
- poj3237 Tree(树链剖分)
- poj3237--Tree(树链剖分+线段树)
- 树链剖分+线段树 poj3237 Tree
- 【POJ3237】Tree(树链剖分+线段树(基于边权))
- 树链剖分+线段树 POJ3237 权值在边 模板
- modbus 功能码
- Grunt教程-前端自动化
- 基于OpenLayers的地图封装Javascript类定义
- Spring:IOC释义(Bean容器、注解、依赖注入)
- oracle行变列(多行变成一行/多行合并成一行/多行合并成多列/合并行)
- 树链剖分 POJ3237
- 文件文档的MIME 参考手册(转自W3C)
- PE总结5---PE文件结构NT头之文件头--IMAGE_FILE_HEADER
- Java锁--synchronized(转载zi http://zhh9106.iteye.com/blog/2151791)
- SQL中的索引
- ViewPager的简单实用
- 关于Socket通信服务的心跳包
- 大型网站数据库和其他优化
- zzulioj 1812: sort (排序&&输入结束判断)