树链剖分学习记录
HDU 3966
基于点权 改动(增减)一条路径上的点 单结点查询
code:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 50010; 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 add_Edge(int u, int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs1(int u, int pre, int d){ deep[u] = d; 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, d+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]) continue; if(v == fa[u]) continue; getpos(v, v); } } int n; int a[maxn]; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[maxn<<2],col[maxn<<2]; void pushdown(int rt, int m) { if(col[rt]) { col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; sum[rt<<1] += (m-(m>>1))*col[rt]; sum[rt<<1|1] += (m>>1)*col[rt]; col[rt] = 0; } } void build(int l,int r,int rt) { col[rt]=0; if(l==r) { sum[rt] = a[fp[l]]; return; } int m=(l+r)>>1; build(lson); build(rson); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&R>=r) { col[rt] += c; sum[rt] += c*(r-l+1); return; } pushdown(rt,r-l+1); int m=(l+r)>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); } int query(int p, int l, int r, int rt){ if(l == r) return sum[rt]; pushdown(rt, r-l+1); int m = (l + r) >> 1; if(p <= m) return query(p, lson); else return query(p, rson); } void change(int u, int v, int val){ int f1 = top[u], f2 = top[v]; while(f1 != f2){ if(deep[f1] < deep[f2]){ swap(f1, f2); swap(u, v); } update(p[f1], p[u], val, 1, n, 1); u = fa[f1]; f1 = top[u]; } if(deep[u] > deep[v]) swap(u, v); update(p[u], p[v], val, 1, n, 1); } int main(){ int M, P; while(scanf("%d%d%d",&n, &M, &P) != EOF){ init(); for(int i = 1; i <= n; i++) scanf("%d",&a[i]); int u, v; while(M--){ scanf("%d%d",&u, &v); add_Edge(u, v); add_Edge(v, u); } dfs1(1, 0, 0); getpos(1, 1); build(1, n, 1); char op[10]; int x, y, z; while(P--){ scanf("%s", op); if(op[0] == 'I'){ scanf("%d%d%d",&x, &y, &z); change(x, y, z); } else if(op[0] == 'D'){ scanf("%d%d%d",&x, &y, &z); change(x, y, -z); } else{ scanf("%d",&x); printf("%d\n",query(p[x], 1, n, 1)); } } } return 0; }
SPOJ QTREE(树链剖分)
基于边权 改动单条边权 查询路径边权最大值
code:
#include<cstdio> #include<cstring> #include<algorithm> #define INF 0x3f3f3f3f using namespace std; const int maxn = 10010; 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 add_Edge(int u, int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs1(int u, int pre, int d){ deep[u] = d; 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){ dfs1(v, u, d+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 != fa[u] && v != son[u]){ getpos(v, v); } } } #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 int n; int sum[maxn<<4]; void pushup(int rt){ sum[rt] = max(sum[rt<<1], sum[rt<<1|1]); } void build(int l, int r, int rt){ sum[rt] = 0; if(l == r) return; int m = (l + r) >> 1; build(lson); build(rson); pushup(rt); } void update(int pp, int vv, int l, int r, int rt){ if(l == r){ sum[rt] = vv; return; } int m = (l + r) >> 1; if(pp <= m) update(pp, vv, lson); else update(pp, vv, rson); pushup(rt); } int query(int L, int R, int l, int r, int rt){ if(L <= l && R >= r){ return sum[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; } int find_(int u, int v){ int f1 = top[u], f2 = top[v]; int tmp = -INF; while(f1 != f2){ // printf("!\n"); if(deep[f1] < deep[f2]){ swap(f1, f2); swap(u, v); } tmp = max(tmp, query(p[f1], p[u], 1, n, 1)); u = fa[f1]; f1 = top[u]; } if(u == v){ return tmp; } if(deep[u] > deep[v]){ swap(u, v); } // printf("* %d %d *\n", u, v); // printf("* %d %d *\n", p[son[u]], p[v]); tmp = max(tmp, query(p[son[u]], p[v], 1, n, 1)); return tmp; } int e[maxn][3]; int main(){ int t; scanf("%d",&t); while(t--){ init(); scanf("%d", &n); int u, v, w; for(int i = 1; i < n; i++){ scanf("%d%d%d", &u, &v, &w); e[i][0] = u; e[i][1] = v; e[i][2] = w; add_Edge(u, v); add_Edge(v, u); } dfs1(1, 0, 0); getpos(1, 1); build(1, n, 1); // for(int i = 1; i <= n; i++){ // printf("i = %d pos = %d\n", i, top[i]); // } for(int i = 1; i < n; i++){ u = e[i][0]; v = e[i][1]; if(deep[u] < deep[v]){ swap(u, v); swap(e[i][0], e[i][1]); } // printf("== %d %d ==\n", p[u], p[v]); update(p[u], e[i][2], 1, n, 1); // printf("bian = %d\n", query(p[u], p[u], 1, n, 1)); } char op[20]; int x, y; while(scanf("%s", op)){ if(op[0] == 'D') break; scanf("%d%d",&x, &y); if(op[0] == 'C'){ // printf("kao = %d\n", p[e[x][0]]); update(p[e[x][0]], y, 1, n, 1); } else{ printf("%d\n", find_(x, y)); } } } return 0; } /* 1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE */