SPOJ GSS7 Can you answer these queries VII(LCT)

来源:互联网 发布:vs2017开发unity3d 编辑:程序博客网 时间:2024/06/03 17:37

题意:维修数列的树上路径版,操作:将一段路径上的点权设为同一个值,求一段路径上的最大字段和。

坑了我好大半天!!!copy维修数列代码的都会被坑惨!!

坑点一:题目中说的最大字段和可以为空。这尼玛哪门子最大字段和还可以为空。。

坑点二:维修数列当中有一个经典的优化:当一个节点有makesame标记,下传的时候可以取消掉reverse标记。原因很明显,当你把一段区间设为同一个值的话,之前的反转操作很显然没意义了。这道题是LCT,节点是始终绑定了的,reverse就是对树的路径的反转,这是一定不能省掉的,即使这段路径有了相同的值,他们内部的关系是一定要维护好的,而维修数列当中节点并没有数组当中固定的位置,数列的第K位是根据size来临时确定的,所以没有关系。

网上写LCT过这道题的人都没换根,佩服他们的勇气。

#include<stdio.h>#include<cstring>#include<algorithm>const int MAXN = 100010;using namespace std;int N, Q;int w[MAXN];void crash() { crash(); }struct Node {    int sz, lmx, rmx, mx, w, sum;    bool rev, sam;    Node*fa, *ch[2], *pfa;Node () ;} nil, *NIL = &nil;Node::Node() {fa = ch[0] = ch[1] = pfa = NIL;sz = 0;rev = sam = 0;w = sum = 0;lmx = rmx = mx = 0;}struct LCT {    #define lch(x) x->ch[0]    #define rch(x) x->ch[1]Node nd[MAXN];void uprev(Node*x){if (x==NIL) return;swap(lch(x), rch(x));swap(x->lmx, x->rmx);x->rev ^= 1;}void upsam(Node*x, int v){if (x==NIL) return;x->w = v;x->sum = v * x->sz;x->mx = x->lmx = x->rmx = max(x->sum, 0);x->sam = 1;}void pushup(Node*x){Node*L = lch(x), *R = rch(x);x->sz = L->sz + R->sz + 1;x->sum = L->sum + R->sum + x->w;x->lmx = max(L->lmx, L->sum+x->w+R->lmx);x->rmx = max(R->rmx, R->sum+x->w+L->rmx);x->mx = max(L->rmx + x->w + R->lmx, max(L->mx, R->mx));}void pushdown(Node*x){if (x==NIL) return;if (x->sam){x->sam = 0;upsam(lch(x), x->w);upsam(rch(x), x->w);}if (x->rev){x->rev = 0;uprev(lch(x));uprev(rch(x));}}void rotate(Node*x){Node *y = x->fa;pushdown(y);pushdown(x);int d = (x==lch(y));y->ch[!d] = x->ch[d];if (x->ch[d] != NIL) x->ch[d]->fa = y;x->fa = y->fa;if (y->fa != NIL)y->fa->ch[ y->fa->ch[1]==y ] = x;x->pfa = y->pfa;y->pfa = NIL;x->ch[d] = y;y->fa = x;pushup(y);}void splay(Node*x, Node*to = NIL){pushdown(x);for (Node *y, *z; x->fa != to; rotate(x)){y = x->fa; z = y->fa;if (z != NIL) rotate((y==lch(z))^(x==lch(y)) ? x : y);}pushup(x);}void access(Node*x){Node*y = NIL;for (; x != NIL; x = x->pfa){splay(x);if (rch(x) != NIL)rch(x)->pfa = x, rch(x)->fa = NIL;x->ch[1] = y;y->fa = x; y->pfa = NIL;pushup(y = x);}}void makeroot(Node*x) {access(x), splay(x), uprev(x);}int quary(int u, int v) {Node*x = nd+u, *y = nd+v;makeroot(x);access(y), splay(y);pushdown(y);if (u == v) return max(y->w, 0);return max(lch(y)->mx, lch(y)->rmx + y->w);}void makesame(int u, int v, int w){Node*x = nd+u, *y = nd+v;makeroot(x);access(y), splay(y);pushdown(y), pushup(y);if (lch(y)!=NIL){pushdown(lch(y)), pushup(lch(y));upsam(y->ch[0], w);pushdown(y->ch[0]);}y->w = w;pushup(y);}} lct;struct Ed {int to; Ed*nxt;}*adj[MAXN], Edges[MAXN*2], *ecnt=Edges;void adde(int a, int b){(++ecnt)->to = b;ecnt->nxt = adj[a];adj[a] = ecnt;}void DFS(int u, int fa){Node&t = lct.nd[u];if (~fa) t.pfa = lct.nd + fa;t.w = w[u];for (Ed*p = adj[u]; p; p=p->nxt)if (p->to != fa) DFS(p->to, u);}int main(){scanf("%d", &N);for (int i = 1; i<=N; ++i)scanf("%d", w+i);for (int i = 1, u, v; i<N; ++i){scanf("%d%d", &u, &v);adde(u, v), adde(v, u);}scanf("%d", &Q);DFS(1, -1);int op, a, b, w;while (Q --) {scanf("%d%d%d", &op, &a, &b);if (op == 1) printf("%d\n", lct.quary(a, b));else scanf("%d", &w), lct.makesame(a, b, w);}return (0 ^ 0);}



0 0