BZOJ3091 城市旅行 LCT

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ3091


题意概括

  鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题。

  可怕,原题是图片,不可以复制题目+删掉废话了……


题解

  http://blog.csdn.net/popoqqq/article/details/40823659

  这位大佬写的很好。

  我的代码在找错的时候一边找,一边该,然后发现和他改的好像……


代码

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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=50005;
struct Gragh{
    int cnt,y[N*2],nxt[N*2],fst[N];
    void clear(){
        cnt=0;
        memset(fst,0,sizeof fst);
    }
    void add(int a,int b){
        y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    }
}g;
int n,m;
int fa[N],son[N][2],rev[N];
LL size[N],val[N],add[N],sum[N],Lsum[N],Rsum[N],Exp[N];
bool isroot(int x){
    return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void pushup(int x){
    int ls=son[x][0],rs=son[x][1],lsz=size[ls],rsz=size[rs];
    size[x]=lsz+rsz+1;
    sum[x]=sum[ls]+sum[rs]+val[x];
    Lsum[x]=Lsum[ls]+(lsz+1)*val[x]+Lsum[rs]+sum[rs]*(lsz+1);
    Rsum[x]=Rsum[rs]+(rsz+1)*val[x]+Rsum[ls]+sum[ls]*(rsz+1);
    Exp[x]=Exp[ls]+Exp[rs]+Lsum[ls]*(rsz+1)+Rsum[rs]*(lsz+1)+val[x]*(lsz+1)*(rsz+1);
}
void pushson(int x,LL v){
    if (!x)
        return;
    val[x]+=v,sum[x]+=v*size[x],add[x]+=v;
    Lsum[x]+=v*size[x]*(size[x]+1)/2;
    Rsum[x]+=v*size[x]*(size[x]+1)/2;
    Exp[x]+=v*size[x]*(size[x]+1)*(size[x]+2)/6;
}
void pushrev(int x){
    rev[x]^=1;
    swap(son[x][0],son[x][1]);
    swap(Lsum[x],Rsum[x]);
}
void pushdown(int x){
    int &ls=son[x][0],&rs=son[x][1];
    if (rev[x]){
        rev[x]=0;
        pushrev(ls);
        pushrev(rs);
    }
    if (add[x]){
        LL &a=add[x];
        pushson(ls,a);
        pushson(rs,a);
        a=0;
    }
}
void pushadd(int x){
    if (!isroot(x))
        pushadd(fa[x]);
    pushdown(x);
}
int wson(int x){
    return son[fa[x]][1]==x;
}
void rotate(int x){
    if (isroot(x))
        return;
    int y=fa[x],z=fa[y],L=wson(x),R=L^1;
    if (!isroot(y))
        son[z][wson(y)]=x;
    fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
    son[y][L]=son[x][R],son[x][R]=y;
    pushup(y),pushup(x);
}
void splay(int x){
    pushadd(x);
    for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
        if (!isroot(y))
            rotate(wson(x)==wson(y)?y:x);
}
void access(int x){
    int t=0;
    while (x){
        splay(x);
        son[x][1]=t;
        pushup(x);
        t=x;
        x=fa[x];
    }
}
void rever(int x){
    access(x);
    splay(x);
    pushrev(x);
}
void link(int x,int y){
    rever(x);
    fa[x]=y;
}
void cut(int x,int y){
    rever(x);
    access(y);
    splay(y);
    fa[x]=son[y][0]=0;
}
int find(int x){
    access(x);
    splay(x);
    while (1){
        pushdown(x);
        if (son[x][0])
            x=son[x][0];
        else
            break;
    }
    return x;
}
void dfs(int x,int pre){
    fa[x]=pre;
    for (int i=g.fst[x];i;i=g.nxt[i])
        if (g.y[i]!=pre)
            dfs(g.y[i],x);
}
LL gcd(LL a,LL b){
    return b==0?a:gcd(b,a%b);
}
void solve(int x,int y){
    if (find(x)!=find(y)){
        puts("-1");
        return;
    }
    rever(x);
    access(y);
    splay(y);
    LL a=Exp[y];
    LL b=size[y]*(size[y]+1)/2;
    LL Gcd=gcd(a,b);
    a/=Gcd,b/=Gcd;
    printf("%lld/%lld\n",a,b);
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++){
        scanf("%lld",&val[i]);
        fa[i]=son[i][0]=son[i][1]=rev[i]=0;
        size[i]=1,Exp[i]=Lsum[i]=Rsum[i]=sum[i]=val[i],add[i]=0;
    }
    g.clear();
    for (int i=1,a,b;i<n;i++){
        scanf("%d%d",&a,&b);
        g.add(a,b),g.add(b,a);
    }
    dfs(1,0);
    for (int i=1;i<=m;i++){
        int op,x,y;
        LL v;
        scanf("%d%d%d",&op,&x,&y);
        if (op==1){
            if (find(x)==find(y))
                cut(x,y);
        }
        else if (op==2){
            if (find(x)!=find(y))
                link(x,y);
        }
        else if (op==3){
            scanf("%lld",&v);
            if (find(x)!=find(y))
                continue;
            rever(x);
            access(y);
            splay(y);
            pushson(y,v);
        }
        else
            solve(x,y);
    }
    return 0;
}

  

posted @   zzd233  阅读(265)  评论(0编辑  收藏  举报
努力加载评论中...

点击右上角即可分享
微信分享提示