POJ 3237 Tree (树链剖分+线段树)
来源:互联网 发布:搞怪照片软件 编辑:程序博客网 时间:2024/05/21 14:45
POJ 3237 Tree
题目大意:
给你n个结点的树,有三种操作:
1.CHANGE i v 将i号边边权变为v
2.NEGATE a b 将a点到b点路径上的边权取相反数
3.QUERY a b 找到a点到b点路径上的边权的最大值
输出所有3操作结果,指令结束标志为”DONE”.
有多组数据.
题目分析:
(又滚去做树链剖分的题,元旦放假前开始做到现在,233)
将边权转化成相连两点中子节点的点权,根无权值.
第一个操作,单点修改;第三个操作,区间最值.
主要是第二个操作,区间取相反数.
维护区间的max和min,便于取反操作.
对于每一个取反操作,区间加标记,交换max和min的值,并且max,min取其相反数.
但是需要注意,线段树的所有操作都要考虑标记的下放,之前没注意这个,WA了.
代码:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=10000+10;const int maxm=20000+10;const int INF=(1<<30);int fir[maxn],nxt[maxm],to[maxm],ecnt;void add_edge(int u,int v){ nxt[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; nxt[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;}int fa[maxn],sz[maxn],son[maxn];void dfs1(int u,int p){ fa[u]=p;sz[u]=1;son[u]=0; for(int i=fir[u];i;i=nxt[i]) if(to[i]!=p) { int v=to[i]; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; }}int top[maxn],dep[maxn],idx[maxn],id;void dfs2(int u,int t,int d){ top[u]=t;dep[u]=d;idx[u]=++id; if(son[u]) dfs2(son[u],t,d+1); for(int i=fir[u];i;i=nxt[i]) if(to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i],d+1);}struct Edge { int u,v,w; Edge(){} Edge(int u,int v,int w):u(u),v(v),w(w){}}tmp[maxn];#define lc (x<<1)#define rc (x<<1|1)#define mid ((l+r)>>1)int val[maxn],maxs[maxn<<2],mins[maxn<<2],tag[maxn<<2];void negat(int x)//取反操作 { tag[x]^=1; swap(maxs[x],mins[x]); maxs[x]*=-1;mins[x]*=-1;}void put_down(int x)//标记下方 { if(!tag[x]) return ; negat(lc);negat(rc); tag[x]=0;}void put_up(int x){ maxs[x]=max(maxs[lc],maxs[rc]); mins[x]=min(mins[lc],mins[rc]);}void build(int x,int l,int r){ if(l==r) maxs[x]=mins[x]=val[l]; else { build(lc,l,mid); build(rc,mid+1,r); put_up(x); }}void change(int x,int l,int r,int q,int v)//单点修改 { if(l==r&&l==q) { maxs[x]=mins[x]=v; return ; } put_down(x);//单点修改时也应将标记下放 if(q<=mid) change(lc,l,mid,q,v); else change(rc,mid+1,r,q,v); put_up(x);}void update(int x,int l,int r,int ql,int qr)//区间取反 { if(ql<=l&&r<=qr) { negat(x); return ; } put_down(x); if(ql<=mid) update(lc,l,mid,ql,qr); if(qr>mid) update(rc,mid+1,r,ql,qr); put_up(x);}int query(int x,int l,int r,int ql,int qr)//区间最值 { if(ql<=l&&r<=qr) return maxs[x]; int L=-INF,R=L; put_down(x); if(ql<=mid) L=query(lc,l,mid,ql,qr); if(qr>mid) R=query(rc,mid+1,r,ql,qr); return max(L,R);}int n;void solve(int x,int y,int k)//k 0 NEGATE 1 QUERY{ int ret=-INF; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); if(k) ret=max(ret,query(1,2,n,idx[top[x]],idx[x])); else update(1,2,n,idx[top[x]],idx[x]); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(idx[y]>idx[x]) { if(k) ret=max(ret,query(1,2,n,idx[x]+1,idx[y])); else update(1,2,n,idx[x]+1,idx[y]); } if(k) printf("%d\n",ret);}void init()//多组数据记得初始化 { ecnt=id=0; memset(fir,0,sizeof(fir)); memset(tag,0,sizeof(tag));}char op[10];int main(){ int T,a,b; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(int u,v,w,i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); add_edge(u,v); tmp[i]=Edge(u,v,w); } dfs1(1,1); dfs2(1,1,1); for(int i=1;i<n;i++) {//边权转化成点权 int u=tmp[i].u,v=tmp[i].v; int f=dep[u]>dep[v]?u:v; val[idx[f]]=tmp[i].w; tmp[i].u=f; } build(1,2,n); while(scanf("%s",op)==1&&op[0]!='D') { scanf("%d%d",&a,&b); if(op[0]=='C') change(1,2,n,idx[tmp[a].u],b); else solve(a,b,op[0]=='N'?0:1); } } return 0;}
0 0
- POJ 3237 Tree(树链剖分+线段树)
- POJ 3237 Tree (树链剖分+线段树)
- POJ 3237 Tree(树链剖分+线段树)
- POJ 3237 Tree (树链剖分+线段树)
- POJ 3237 Tree (树链剖分+线段树)
- |poj 3237|树链剖分|线段树|Tree
- poj 3237 Tree 树链剖分 线段树
- POJ 3237 Tree(树链剖分 线段树区间标记)
- poj 3237 Tree(树链剖分,点权,线段树)
- 【POJ】【P3237】【Tree】【题解】【树链剖分+线段树】
- POJ 3237Tree(树链剖分-线段树点更新-区间更新-区间最值查询-入边)
- 线段树 POJ 3321 Apple Tree
- poj 3321 Apple Tree 线段树
- POJ 3321 Apple Tree 线段树
- POJ 3321 Apple Tree 线段树+DFS
- poj 3321 Apple Tree(线段树)
- poj 3321 Apple Tree 线段树
- POJ 3321 Apple Tree 线段树
- ANSI C标准之值保留(value preserving)原则
- Vue.js系列之vue-router(上)(3)
- Java Swing 如何使用JTree(2)
- S5PV210 内存配置(地址空间和片选)
- 用C++画一个圆
- POJ 3237 Tree (树链剖分+线段树)
- Java深海拾遗系列(1)---java浮点型数操作准确性问题刨析
- Java Swing 如何使用JTree(3)
- 【转载】UML类图几种关系的总结
- git 相关
- jQuery如何操作ajax
- 汽车加油问题
- win10系统配置java环境变量
- 引用NDK自带例子