zoukankan      html  css  js  c++  java
  • LCT模板(BZOJ2631)

    用LCT实现路径加,路径乘,断开及加上一条边(保证是树),查询路径和。

    #include <cstdio>
    #include <algorithm>
    #define l(x) t[x].s[0]
    #define r(x) t[x].s[1]
    #define f(x) t[x].f
    #define lc(x) (r(f(x)) == x)
    #define int unsigned int
    
    const int N = 100005, p = 51061;
    char op[2];
    int n,m,x,y,c,tp,q[N];
    struct nd {int v,f,s[2],sm,sz,mu,ad,rv;}t[N];
    
    bool rt(int x) {return l(f(x)) != x && r(f(x)) != x;}
    void cal(int x, int m, int a) {
        if(!x) return;
        t[x].v = (t[x].v*m+a)%p, t[x].sm = (t[x].sm*m+a*t[x].sz)%p, t[x].mu = t[x].mu*m%p, t[x].ad = (t[x].ad*m+a)%p;
    }
    
    void pu(int x) {t[x].sm = (t[l(x)].sm+t[r(x)].sm+t[x].v)%p, t[x].sz = (t[l(x)].sz+t[r(x)].sz+1)%p;}
    void pd(int x) {
        if(t[x].rv) t[x].rv = 0, t[l(x)].rv ^= 1, t[r(x)].rv ^= 1, std::swap(l(x),r(x));
        if(t[x].mu != 1 || t[x].ad) cal(l(x),t[x].mu,t[x].ad),cal(r(x),t[x].mu,t[x].ad);
        t[x].mu = 1, t[x].ad = 0;
    }
    void rot(int x) {
        int y = f(x), z = f(y), xx = r(y)==x;
        if(!rt(y)) t[z].s[r(z)==y] = x;
        f(x) = z, f(y) = x, f(t[x].s[!xx]) = y;
        t[y].s[xx] = t[x].s[!xx], t[x].s[!xx] = y;
        pu(y);
    }
    void sp(int x) {
        q[++tp] = x;
        for(int i = x; !rt(i); i = f(i)) q[++tp] = f(i);
        while(tp) pd(q[tp--]);
        for(int y = f(x); !rt(x); rot(x),y=f(x)) if(!rt(y)) {
            if(lc(x)^lc(y)) rot(x); else rot(y);
        }
        pu(x);
    }
    
    void acs(int x) {for(int y = 0; x; x = f(x)) sp(x), r(x) = y, pu(y=x);}
    void mkrt(int x) {acs(x), sp(x), t[x].rv ^= 1;}
    void spli(int x, int y) {mkrt(y), acs(x), sp(x);}
    void lk(int x, int y) {mkrt(x), f(x) = y;}
    void cut(int x, int y) {mkrt(x), acs(y), sp(y), l(y) = f(x) = 0, pu(y);}
    
    signed main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) t[i].v = t[i].sm = t[i].sz = t[i].mu = 1;
        for(int i = 1; i < n; i++) scanf("%d%d", &x, &y), lk(x,y);
        while(m--) {
            scanf("%s%d%d", op, &x, &y);
            if(op[0] == '+') scanf("%d", &c), spli(x,y), cal(x,1,c);
            else if(op[0] == '-') cut(x,y), scanf("%d%d", &x, &y), lk(x,y);
            else if(op[0] == '*') scanf("%d", &c), spli(x,y), cal(x,c,0);
            else spli(x,y), printf("%d
    ", t[x].sm);
        }
        return 0;
    }
  • 相关阅读:
    final、static关键字
    this关键字与super关键字区别
    JAVA常见报错
    Java抽象类和多态
    Java 类和接口的继承
    JAVA封装
    库存管理案例
    Map的遍历
    LinkedList vector集合,Set接口
    Collection,迭代器iterator,list接口
  • 原文地址:https://www.cnblogs.com/juruolty/p/6222748.html
Copyright © 2011-2022 走看看