BZOJ 2631: tree

Description

 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:

  • u v c:将u到v的路径上的点的权值都加上自然数c;

– u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;

  • u v c:将u到v的路径上的点的权值都乘上自然数c;

/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

Input

第一行两个整数n,q

接下来n-1行每行两个正整数u,v,描述这棵树

接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2

1 2

2 3

  • 1 3 4

/ 1 1

Sample Output

4

HINT

数据规模和约定

10%的数据保证,1<=n,q<=2000

另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

100%的数据保证,1<=n,q<=10^5,0<=c<=10^4

Solution

LCT裸题,是BZOJ1798的LCT版本。对于如何标记有问题的同学,建议先做1798。这道题开long long容易TLE,用unsigned即可。

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <cstdio>
#include <iostream>
using namespace std;
const int N=100005;
int getint() {
    int r = 0; char c = getchar();
    for (; '0' > c || c > '9'; c = getchar());
    for(;'0'<=c&&c<='9';c=getchar())r=r*10-'0'+c;
    return r;
}
char getop() {
    char c = getchar();
    for(;c<42||c>47;c=getchar());
    return c;
}
typedef unsigned LL;
const LL mod = 51061;
int c[N][2],fa[N],rev[N],st[N];
LL mul[N],plu[N],tree[N],sum[N],siz[N];
bool isroot(int x) {
    return !(c[fa[x]][0]==x||c[fa[x]][1]==x);
}
void pd(int x) {
    int l=c[x][0], r=c[x][1];
    if (rev[x]){
        rev[l]^=1;
        rev[r]^=1;
        rev[x]=0;
        swap(c[x][0],c[x][1]);
    }
    if (mul[x]!=1||plu[x]!=0){
        sum[l]=(sum[l]*mul[x]+siz[l]*plu[x])%mod;
        mul[l]=(mul[l]*mul[x])%mod;
        plu[l]=(plu[l]*mul[x]+plu[x])%mod;
        sum[r]=(sum[r]*mul[x]+siz[r]*plu[x])%mod;
        mul[r]=(mul[r]*mul[x])%mod;
        plu[r]=(plu[r]*mul[x]+plu[x])%mod;
        tree[x]=(tree[x]*mul[x]+plu[x])%mod;
        mul[x]=1;plu[x]=0;
    }
}
void pu(int x) {
    int l=c[x][0],r=c[x][1];
    siz[x]=siz[l]+siz[r]+1;
    sum[x]=(sum[l]+sum[r]+tree[x])%mod;
}
void rotate(int x){
    int y=fa[x], z=fa[y], a=(c[fa[x]][1]==x), b=!a;
    if(!isroot(y)) c[z][c[z][1]==y]=x;
    fa[x]=z;fa[y]=x;fa[c[x][b]]=y;
    c[y][a]=c[x][b];c[x][b]=y;
    pu(y);pu(x);
}
void splay(int x) {
    int t=1;st[1]=x;
    for(int i=x;!isroot(i);i=fa[i]) st[++t]=fa[i];
    while(t) pd(st[t--]);
    while(!isroot(x)){
        int y=fa[x],z=fa[y];
        if(!isroot(y)){
            if(c[y][0]==x^c[z][0]==y)rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x){
    int y = 0;
    while(x){
        splay(x);
        c[x][1]=y;
        pu(x);
        y=x;
        x=fa[x];
    }
}
void mkrt(int x){ access(x);splay(x);rev[x]^=1; }
void cut(int x, int y) {
    mkrt(x);
    access(y);
    splay(y);
    c[y][0]=0;
    fa[x]=0;
}
void link(int x, int y) {
    mkrt(x);
    fa[x]=y;
    splay(x);
}
int n, q;
void chanp(int x, int y, LL pluval) {
    mkrt(x);
    access(y);
    splay(y);
    sum[y]=(sum[y]+siz[y]*pluval)%mod;
    mul[y]=(mul[y])%mod;
    plu[y]=(plu[y]+pluval)%mod;
}
void chanm(int x, int y, LL mulval) {
    mkrt(x);
    access(y);
    splay(y);
    sum[y]=(sum[y]*mulval)%mod;
    mul[y]=(mul[y]*mulval)%mod;
    plu[y]=(plu[y]*mulval)%mod;
}
LL query(int x, int y) {
    mkrt(x);
    access(y);
    splay(y);
    return sum[y]%mod;
}
int main() {
    n=getint();q=getint();
    for (int i = 1; i <= n; ++i) tree[i]=siz[i]=sum[i]=mul[i]=1,plu[i]=0;
    int x,y,z,zz;
    char o;
    for(int i=1;i<n;++i){
        x=getint();
        y=getint();
        link(x,y);
    }
    while (q--){
        o=getop();
        if(o=='+'){
            x=getint();y=getint();z=getint();
            chanp(x,y,z);
        }
        if(o=='-'){
            x=getint();y=getint();z=getint();zz=getint();
            cut(x,y);link(z,zz);
        }
        if(o=='*'){
            x=getint();y=getint();z=getint();
            chanm(x,y,z);
        }
        if(o=='/'){
            x=getint();y=getint();
            printf("%u\n", query(x,y));
        }
    }
}