[kuangbin]树链剖分 C - Tree
和平常的树链剖分维护边权不同的地方在于对线段树的要求较高
NEGATE
反转区间,也就是a - b 内所有的边权取相反数
而Query询问是最大值,所以也就是维护可取反区间的最大值问题
需要维护的值是区间最大值,区间最小值(反转取件后交换其值),lazy标记(优化加速,标记完全反转最大区间)
int rmax[maxn<<2],rmin[maxn<<2],lazy[maxn<<2];
对应线段树的push_up和push_down操作也就很稳了(就是维护那几个值)
void pup(int rt) { rmax[rt] = max(rmax[rs] , rmax[ls]); rmin[rt] = min(rmin[rs] , rmin[ls]); } void pdown(int rt) { if(lazy[rt]) { rmax[ls] = -rmax[ls]; rmin[ls] = -rmin[ls]; swap(rmax[ls],rmin[ls]); rmax[rs] = -rmax[rs]; rmin[rs] = -rmin[rs]; swap(rmax[rs],rmin[rs]); lazy[ls] ^= 1; lazy[rs] ^= 1; lazy[rt] = 0; } }
有一个要注意的地方就是本题有一个点边权更新问题,需要把lazy标记清空一下
好了其他的就是模板问题了
树链做到这基础的的就差不多了,自我感觉还比较良好——嘿嘿嘿心态嘛
/* https://vjudge.net/contest/251031#problem/F 像是经典的树链剖分,用一下模板 */ #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define lson rt<<1,left,mid #define rson rt<<1|1,mid+1,right #define ls rt<<1 #define rs rt<<1|1 #define mid ((left + right) >> 1) #define inf (1 << 28) using namespace std; typedef long long ll; const int maxn = 1e4 + 1e3; int n,m,p; int V[maxn]; //邻接表 struct node{ int to,pre; }e[maxn << 1]; struct road{ int x,y,v; }r[maxn<<1]; int id[maxn],cnt; //线段树 int rmax[maxn<<2],rmin[maxn<<2],lazy[maxn<<2]; //dfs1 int siz[maxn],dep[maxn],fa[maxn],son[maxn]; //dfs2 int top[maxn],num_id[maxn],id_num[maxn]; int tot; void init() { memset(id,-1,sizeof(id)); memset(son,0,sizeof(son)); cnt = tot = 0; } void add(int from,int to) { e[cnt].to = to; e[cnt].pre = id[from]; id[from] = cnt++; } void dfs1(int now,int f,int depth) { siz[now] = 1; fa[now] = f; dep[now] = depth; for(int i = id[now];~i;i = e[i].pre) { int to = e[i].to; if(to != f) { dfs1(to,now,depth+1); siz[now] += siz[to]; if(siz[to] > siz[son[now]]) son[now] = to; } } } void dfs2(int now,int rt) { top[now] = rt; num_id[now] = ++tot; id_num[tot] = now; if(!son[now]) return; dfs2(son[now],rt); for(int i = id[now];~i;i = e[i].pre) { int to = e[i].to; if(to != son[now] && to != fa[now]) { dfs2(to,to); } } } void pup(int rt) { rmax[rt] = max(rmax[rs] , rmax[ls]); rmin[rt] = min(rmin[rs] , rmin[ls]); } void pdown(int rt) { if(lazy[rt]) { rmax[ls] = -rmax[ls]; rmin[ls] = -rmin[ls]; swap(rmax[ls],rmin[ls]); rmax[rs] = -rmax[rs]; rmin[rs] = -rmin[rs]; swap(rmax[rs],rmin[rs]); lazy[ls] ^= 1; lazy[rs] ^= 1; lazy[rt] = 0; } } void build(int rt,int left,int right) { lazy[rt] = 0; if(left == right) { rmax[rt] = V[id_num[left]]; rmin[rt] = V[id_num[left]]; return; } build(lson); build(rson); pup(rt); } void updata(int rt,int left,int right,int l,int r,int k) { if(left == l && right == r) { rmax[rt] = k; rmin[rt] = k; lazy[rt] = 0;//就算翻转了也可以清除标记了 return; } pdown(rt); if(r <= mid) updata(lson,l,r,k); else if(l > mid) updata(rson,l,r,k); else { updata(lson,l,mid,k); updata(rson,mid+1,r,k); } pup(rt); } void ne_updata(int rt,int left,int right,int l,int r) { if(l <= left && right <= r) { lazy[rt] ^= 1; rmax[rt] = -rmax[rt]; rmin[rt] = -rmin[rt]; swap(rmax[rt],rmin[rt]); //cout<<rmax[rt]<<" "<<rmin[rt]<<endl; return; } pdown(rt); if(l <= mid) ne_updata(lson,l,r); if(r > mid) ne_updata(rson,l,r); pup(rt); } void updata_lca(int x,int y) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); ne_updata(1,1,tot,num_id[top[x]],num_id[x]); x = fa[top[x]]; } if(x == y)return; if(dep[x] < dep[y]) { swap(x,y); } ne_updata(1,1,tot,num_id[son[y]],num_id[x]); return ; } int query(int rt,int left,int right,int l,int r) { int res; res = -inf; if(l <= left && right <= r) { return rmax[rt]; } pdown(rt); if(l <= mid) { res = max(res,query(lson,l,r)); } if(r > mid) { res = max(res,query(rson,l,r)); } return res; } int querty_lca(int x,int y) { int res; res = -inf; //cout<<top[x]<<" "<<top[y]<<endl; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); res = max(res,query(1,1,tot,num_id[top[x]],num_id[x])); x = fa[top[x]]; } if(x == y)return res; if(dep[x] < dep[y]) { swap(x,y); } res = max(res,query(1,1,tot,num_id[son[y]],num_id[x])); return res; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); init(); int from,to,cost; for(int i=1;i<=n-1;i++) { scanf("%d%d%d",&from,&to,&cost); r[i].x = from; r[i].y = to; r[i].v = cost; add(from,to); add(to,from); } dfs1(1,0,1); dfs2(1,1); for(int i=1;i<=n;++i) { if(dep[r[i].x] < dep[r[i].y]) swap(r[i].x,r[i].y); V[r[i].x] = r[i].v; } build(1,1,tot); //cout<<sum[4]<<" "<<sum[5]<<" "<<sum[6]<<" "<<sum[7]<<endl; char op[10]; int x,y,z; while(1) { scanf("%s",op); if(op[0] == 'Q'){ scanf("%d%d",&x,&y); printf("%d\n",querty_lca(x,y)); } else if(op[0] == 'C') { scanf("%d%d",&x,&z); updata(1,1,tot,num_id[r[x].x],num_id[r[x].x],z); } else if(op[0] == 'N') { scanf("%d%d",&x,&y); updata_lca(x,y); } else { break; } } } return 0; }
加油吧!有生活,有代码,不迷失,不深陷,体验生活,享受快乐!