poj 3237 Tree(树链剖分)
2017-11-07 23:12
357 查看
wa了半天。。懒惰标记那里要用异或来修改,wa的时候突然想到,万一两次反转相同的区间,反转就取消了,然而我的懒惰标记那里一直col[rt]=1,这样反转就没有取消。。。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int MAXN = 1e5+10; const int INF = 0x3f3f3f3f; struct Edge { int to,next; } edge[MAXN*2]; int head[MAXN],tot; int top[MAXN]; int fa[MAXN]; int deep[MAXN]; int num[MAXN]; int p[MAXN]; int fp[MAXN]; int son[MAXN]; int pos; void init() { tot = 0; memset(head,-1,sizeof(head)); pos = 1; memset(son,-1,sizeof(son)); } void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs1(int u, int pre, int dep) { deep[u] = dep; fa[u] = pre; num[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == pre) continue; dfs1(v,u,dep+1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } void getpos(int u, int sp) { top[u] = sp; p[u] = pos++; fp[p[u]] = u; if(son[u] == -1) return; getpos(son[u],sp); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u]) getpos(v,v); } } int e[MAXN][3]; int n; char op[15]; int maxn[MAXN<<2]; int minn[MAXN<<2]; int col[MAXN<<2]; void pushUp(int rt) { maxn[rt] = max(maxn[rt<<1], maxn[rt<<1|1]); minn[rt] = min(minn[rt<<1], minn[rt<<1|1]); } void pushDown(int rt) { if(col[rt]) { col[rt] = 0; col[rt<<1] ^= 1; col[rt<<1|1] ^= 1; maxn[rt<<1] = -maxn[rt<<1]; minn[rt<<1] = -minn[rt<<1]; swap(maxn[rt<<1],minn[rt<<1]); maxn[rt<<1|1] = -maxn[rt<<1|1]; minn[rt<<1|1] = -minn[rt<<1|1]; swap(maxn[rt<<1|1],minn[rt<<1|1]); } } void update(int pos, int val, int l, int r, int rt) { if(l == r) { minn[rt] = maxn[rt] = val; return; } pushDown(rt); int mid = (l+r) >> 1; if(pos <= mid) update(pos,val,l,mid,rt<<1); else update(pos,val,mid+1,r,rt<<1|1); pushUp(rt); } void updateTwo(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) { maxn[rt] = -maxn[rt]; minn[rt] = -minn[rt]; swap(maxn[rt],minn[rt]); col[rt] ^= 1; return; } pushDown(rt); int mid = (l+r) >> 1; if(L <= mid) updateTwo(L,R,l,mid,rt<<1); if(R > mid) updateTwo(L,R,mid+1,r,rt<<1|1); pushUp(rt); } int query(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return maxn[rt]; pushDown(rt); int mid = (l+r) >> 1; int ret = -INF; if(L <= mid) ret = max(ret,query(L,R,l,mid,rt<<1)); if(R > mid) ret = max(ret,query(L,R,mid+1,r,rt<<1|1)); return ret; } int Calc(int u, int v) { int f1 = top[u],f2 = top[v]; int ret = -INF; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1,f2); swap(u,v); } ret = max(ret,query(p[f1],p[u],1,n,1)); u = fa[f1]; f1 = top[u]; } if(u == v) return ret; if(deep[u] > deep[v]) swap(u,v); ret = max(ret,query(p[son[u]],p[v],1,n,1)); return ret; } void flip(int u, int v) { int f1 = top[u],f2 = top[v]; while(f1 != f2) { if(deep[f1] < deep[f2]) { swap(f1,f2); swap(u,v); } updateTwo(p[f1],p[u],1,n,1); u = fa[f1]; f1 = top[u]; } if(u == v) return; if(deep[u] > deep[v]) swap(u,v); updateTwo(p[son[u]],p[v],1,n,1); } int main() { int T; scanf("%d",&T); while(T--) { init(); memset(maxn,0,sizeof(maxn)); memset(minn,0,sizeof(minn)); memset(col,0,sizeof(col)); scanf("%d",&n); for(int i = 1; i < n; ++i) { scanf("%d %d %d",&e[i][0],&e[i][1],&e[i][2]); addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } dfs1(1,0,0); getpos(1,1); for(int i = 1; i < n; ++i) { if(deep[e[i][0]] > deep[e[i][1]]) swap(e[i][0],e[i][1]); update(p[e[i][1]],e[i][2],1,n,1); } int u,v; while(scanf("%s",op) && op[0] != 'D') { scanf("%d %d",&u,&v); //最值查询 if(op[0] == 'Q') printf("%d\n",Calc(u,v)); //单点修改 else if(op[0] == 'C') update(p[e[u][1]],v,1,n,1); //区间取相反数 else flip(u,v); } } return 0; }
相关文章推荐
- POJ 3237 Tree (树链剖分)
- 【SPOJ 375】 【POJ 3237】 375. Query on a 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 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 3237 Tree (树链剖分)