poj 3237 加强版 query on a tree 树链剖分
来源:互联网 发布:怎样打开Windows目录 编辑:程序博客网 时间:2024/06/01 08:03
链接:
http://www.spoj.pl/problems/QTREE/
http://poj.org/problem?id=3237
题意:一棵树,两种更新操作,改变一条边的边权,将a ->b路径上的所有边权取反,询问一条路径上的最大边权
都是典型的树链剖分,下面一题是上面的加强版,还要在树上进行成段更新,其实也不难。
只是区间还要再记录一个最小值,因为取反操作的话会使得区间的最大值和最小值互换。
然后就是树链剖分的老套路,如果是重链,在线段树中更新,否则直接改变边权。
线段树中下放懒惰标记的时候写漏了,调了许久,囧爆了。。。。
好像还可以用动态树实现吧,概念都看懂了,只是没实践过,改天去学了再贴上来吧
下面是这两题的代码,我的代码有点搓 - -,观看请慎重,以免伤了眼*_*
spoj 375 query on a tree
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 20010;const int inf = ~0u>>2;int M[maxn<<2];struct node{ int s,t,w,next;}edge[maxn*2];int E,n;int size[maxn] , fa[maxn] , heavy[maxn] , head[maxn] , dep[maxn] , rev[maxn] , num[maxn] , cost[maxn];int Seg_size;inline void Max(int &x,int y){if(x<y) x=y;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void add_edge(int s,int t,int w){ edge[E].w=w; edge[E].s=s; edge[E].t=t; edge[E].next=head[s]; head[s]=E++;}void dfs(int u,int f){ int mx=-1,e=-1; size[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].t; if(v==f) continue; dep[v]=dep[u]+1; rev[v]=i^1; dfs(v,u); size[u]+=size[v]; if(size[v]>mx) { mx=size[v]; e=i; } } heavy[u]=e; if(e!=-1) fa[edge[e].t]=u;}inline void pushup(int rt){ M[rt]=max(M[rt<<1],M[rt<<1|1]);}void build(int l,int r,int rt){ M[rt]=inf; if(l==r){ return ; } int m=(l+r)>>1; build(lson); build(rson);}void update(int p,int val,int l,int r,int rt){ if(l==r){ M[rt]=val; return ; } int m=(l+r)>>1; if(p<=m) update(p,val,lson); else update(p,val,rson); pushup(rt);}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return M[rt]; } int m=(l+r)>>1; int ret=0; if(L<=m) ret=max(ret,query(L,R,lson)); if(R>m) ret=max(ret,query(L,R,rson)); return ret;}void prepare(){ build(1,n-1,1); memset(num,-1,sizeof(num)); dep[0]=0;Seg_size=0; for(int i=0;i<n;i++) fa[i]=i; dfs(0,0); for(int i=0;i<n;i++) { if(heavy[i]==-1) { int pos=i; while(pos && edge[heavy[edge[rev[pos]].t]].t == pos) { int t=rev[pos]; num[t]=num[t^1]=++Seg_size; update(Seg_size,edge[t].w,1,n-1,1); pos=edge[t].t; } } }}void change(int edge_id,int val){ if(num[edge_id]==-1) edge[edge_id].w=edge[edge_id^1].w=val; else update(num[edge_id],val,1,n-1,1);}int calc(int u,int lca){ int ans=-inf;int vi=0; while(u!=lca) { vi++; if(vi==10) break; int r=rev[u]; if(num[r]==-1) Max(ans,edge[r].w),u=edge[r].t; else { int p=fa[u]; if(dep[p] < dep[lca]) p=lca; int l=num[r]; int r=num[heavy[p]]; Max(ans,query(l,r,1,n-1,1)); u=p; } } return ans;}int lca(int u,int v){ while(1) { int a=find(u),b=find(v); if(a==b) return dep[u] < dep[v] ? u : v;//a,b在同一条重链上 else if(dep[a]>=dep[b]) u=edge[rev[a]].t; else v=edge[rev[b]].t; }}int solve(int u,int v){ int p=lca(u,v); return max(calc(u,p),calc(v,p));}int main(){ int t,i,a,b,c; scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); E=0; scanf("%d",&n); for(i=0;i<n-1;i++) { scanf("%d%d%d",&a,&b,&c);a--;b--; add_edge(a,b,c); add_edge(b,a,c); } prepare(); char op[20]; while(scanf("%s",op)!=EOF && strcmp(op,"DONE")) { if(op[0]=='C') { scanf("%d%d",&a,&c); change((a-1)*2,c); } else { scanf("%d%d",&a,&b); printf("%d\n",solve(a-1,b-1)); } } } return 0;}/*131 2 12 3 2QUERY 1 2CHANGE 1 3QUERY 1 2DONE13171 2 11 3 22 4 32 5 43 6 53 7 6Query 1 7*/
poj 3237
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 100010;const int inf = ~0u>>2;int M[maxn<<2];int Mi[maxn<<2];int col[maxn<<2];struct node{int s,t,w,next;}edge[maxn*2];int E,n;int size[maxn] , fa[maxn] , heavy[maxn] , head[maxn] , dep[maxn] , rev[maxn] , num[maxn] , cost[maxn];int Seg_size;inline void Max(int &x,int y){if(x<y) x=y;}inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a>b?b:a;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void add_edge(int s,int t,int w){edge[E].w=w;edge[E].s=s;edge[E].t=t;edge[E].next=head[s];head[s]=E++;}void dfs(int u,int f){int mx=-1,e=-1;size[u]=1;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].t;if(v==f) continue;dep[v]=dep[u]+1;rev[v]=i^1;dfs(v,u);size[u]+=size[v];if(size[v]>mx){mx=size[v];e=i;}}heavy[u]=e;if(e!=-1) fa[edge[e].t]=u;}void build(int l,int r,int rt){Mi[rt]=inf;M[rt]=-inf;col[rt]=0;if(l==r){return ;}int m=(l+r)>>1;build(lson);build(rson);}inline void pushup(int rt){M[rt]=max(M[rt<<1],M[rt<<1|1]);Mi[rt]=min(Mi[rt<<1],Mi[rt<<1|1]);}void make(int rt){int tmp=Mi[rt];Mi[rt]=-M[rt];M[rt]=-tmp;}void pushdown(int rt){if(col[rt]){ col[rt<<1]^=1; make(rt<<1); col[rt<<1|1]^=1; make(rt<<1|1); col[rt]=0;//很久没写线段树,连这个都忘了,囧}}void update(int p,int val,int l,int r,int rt){if(l==r){ Mi[rt]=M[rt]=val; return ;}pushdown(rt);int m=(l+r)>>1;if(p<=m) update(p,val,lson);else update(p,val,rson);pushup(rt);}void justdoit(int L,int R,int l,int r,int rt){//printf("L=%d R=%d l=%d r=%d\n",L,R,l,r);if(L<=l&&r<=R){col[rt]^=1;make(rt);return ;}pushdown(rt);int m=(l+r)>>1;if(L<=m) justdoit(L,R,lson);if(R>m) justdoit(L,R,rson);pushup(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l&&r<=R){return M[rt];}pushdown(rt);int m=(l+r)>>1;int ret=-inf;if(L<=m) ret=max(ret,query(L,R,lson));if(R>m) ret=max(ret,query(L,R,rson));return ret;}void prepare(){build(1,n-1,1);memset(num,-1,sizeof(num));dep[0]=0;Seg_size=0;for(int i=0;i<n;i++) fa[i]=i;dfs(0,0);for(int i=0;i<n;i++){if(heavy[i]==-1){int pos=i;while(pos && edge[heavy[edge[rev[pos]].t]].t == pos){int t=rev[pos];num[t]=num[t^1]=++Seg_size;update(Seg_size,edge[t].w,1,n-1,1);pos=edge[t].t;}}}}void change(int edge_id,int val){if(num[edge_id]==-1) edge[edge_id].w=edge[edge_id^1].w=val;else update(num[edge_id],val,1,n-1,1);}int calc(int u,int lca){int ans=-inf; while(u!=lca){int r=rev[u];if(num[r]==-1) Max(ans,edge[r].w),u=edge[r].t;else {int p=fa[u];if(dep[p] < dep[lca]) p=lca;int l=num[r];int r=num[heavy[p]];Max(ans,query(l,r,1,n-1,1));u=p;}}return ans;}void gao(int u,int lca){while(u!=lca){int r=rev[u];if(num[r]==-1) edge[r].w=edge[r^1].w=-edge[r].w,u=edge[r].t;else{int p=fa[u];if(dep[p] < dep[lca]) p=lca;int l=num[r];int r=num[heavy[p]];//printf("l=%d r=%d\n",l,r);justdoit(l,r,1,n-1,1);u=p;}}}int lca(int u,int v){while(1){int a=find(u),b=find(v);if(a==b) return dep[u] < dep[v] ? u : v;//a,b在同一条重链上else if(dep[a]>=dep[b]) u=edge[rev[a]].t;else v=edge[rev[b]].t;}}int solve(int u,int v){int p=lca(u,v);return max(calc(u,p),calc(v,p));}void sol(int u,int v){int p=lca(u,v);//printf("p=%d\n",p);gao(u,p);gao(v,p);}int main(){int t,i,a,b,c;scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));E=0;scanf("%d",&n);for(i=0;i<n-1;i++){scanf("%d%d%d",&a,&b,&c);a--;b--;add_edge(a,b,c);add_edge(b,a,c);}prepare();char op[20];while(scanf("%s",op)!=EOF && strcmp(op,"DONE")){if(op[0]=='C'){scanf("%d%d",&a,&c);change((a-1)*2,c);}else if(op[0]=='N'){scanf("%d%d",&a,&b);if(a==b) while(1);sol(a-1,b-1);}else {scanf("%d%d",&a,&b);if(a==b) while(1);printf("%d\n",solve(a-1,b-1));}}}return 0;}
- poj 3237 加强版 query on a tree 树链剖分
- 【SPOJ 375】 【POJ 3237】 375. Query on a tree 树链剖分
- Query on A Tree
- [SPOJ 375]Query On a Tree(树链剖分)
- SPOJ 375. Query on a tree【树链剖分】
- SPOJ 375. Query on a tree【树链剖分】
- 树链剖分 375. Query on a tree
- SPOJ QTREE(Query on a tree树链剖分)
- SPOJ375--Query on a tree(树链剖分)
- spoj 375--Query On a Tree [树链剖分]
- Query on a tree 树链剖分 第一次写
- spoj375 Query on a tree 树链剖分
- spoj 375 Query on a tree 树链剖分
- spoj 375. Query on a tree(树链剖分)
- SPOJ QTREE Query on a tree --树链剖分
- spoj375 Query on a tree 树链剖分
- 【树链剖分】spoj375 Query on a tree
- [ SPOJ - QTREE]Query on a tree && 树链剖分
- js格式化日期
- 20120821-BeginPaint()和EndPaint()
- ROW_NUMBER()用法
- commons-fileupload介绍
- HDU 1690 Bus System
- poj 3237 加强版 query on a tree 树链剖分
- POJ 1755 Triathlon【半平面交】
- Webkit中HTML5 Video的实现分析 (四) - 视频加载及播放的时序图
- 自定义java类实现类似spring的依赖注入功能
- ext4 date 汉化
- 开源项目管理软件redmine-什么时候用,怎么用?(二)
- Receiver XXX type for instance message is a forward declaration
- C++学习:一个简单适用的跨平台Log类(1)
- Vim+cscope+ctags+tags阅读源代码