bc的题。今天bc又挂了。这题没有写完,然后b题fst了。伤心啊。
其实思路比较简单。直接链剖dfs序上把所有区间找出来swap就好了。不过代码实现起来还是比较麻烦的,很容易绕晕。加上smt久了没写手生了,于是就调了一晚上。唉,我还是太年轻了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct node {
int v, s, sz, w, rv;
node *ls, *rs;
inline void update() {
sz = 1;
s = v;
if (ls) {
sz += ls-> sz;
s += ls-> s;
}
if (rs) {
sz += rs-> sz;
s += rs-> s;
}
}
inline void fix() {
if (rv) {
swap(ls, rs);
if (ls)
ls-> rv ^= 1;
if (rs)
rs-> rv ^= 1;
rv = 0;
}
}
};
typedef pair <node*, node*> npr;
const int maxn = 80009;
#define szof(p) ((p)?(p->sz):0)
#define sof(p) ((p)?(p->s):0)
node nlst[maxn << 1], *np(nlst);
node* newNode(int v) {
np-> ls = np-> rs = 0;
np-> v = np-> s = v;
np-> sz = 1;
np-> rv = 0;
#ifdef WIN32
np-> w = (rand() << 16) | rand();
#else
np-> w = rand();
#endif
return np ++;
}
node* merge(node* p, node* q) {
if (p)
p-> fix();
else
return q;
if (q)
q-> fix();
else
return p;
if (p-> w > q-> w) {
p-> rs = merge(p-> rs, q);
p-> update();
return p;
}
else {
q-> ls = merge(p, q-> ls);
q-> update();
return q;
}
}
npr split(node* p, int k) {
if (!k)
return npr(0, p);
else if (!p || p-> sz == k)
return npr(p, 0);
else {
p-> fix();
if (k <= szof(p-> ls)) {
npr g(split(p-> ls, k));
p-> ls = g. second;
p-> update();
return npr(g. first, p);
}
else {
npr g(split(p-> rs, k - szof(p-> ls) - 1));
p-> rs = g. first;
p-> update();
return npr(p, g. second);
}
}
}
int smtQry(node* p, int k) {
int s(0);
while (p && k) {
p-> fix();
if (k <= szof(p-> ls))
p = p-> ls;
else
s += sof(p-> ls) + p-> v, k -= szof(p-> ls) + 1, p = p-> rs;
}
return s;
}
struct edge {
int t;
edge *next;
};
edge *head[maxn], elst[maxn << 1], *ep(elst);
inline void addEdge(int u, int v) {
ep-> t = v;
ep-> next = head[u];
head[u] = ep ++;
}
int v[maxn], n, m;
int tc, fa[maxn], d[maxn], sz[maxn], fs[maxn], fc[maxn], ch[maxn];
int dfb[maxn], dfo[maxn];
node *rt, *remp;
void divide() {
static int stc[maxn];
int tst(1), dfn(0);
memset(fa, 0, sizeof(fa));
stc[tst] = 1;
while (tst) {
int p(stc[tst --]);
dfo[++ dfn] = p;
for (edge* e = head[p]; e; e = e-> next)
if (e-> t ^ fa[p]) {
fa[e-> t] = p;
d[e-> t] = d[p] + 1;
stc[++ tst] = e-> t;
}
}
tc = 0;
for (int i = n; i; -- i) {
int p(dfo[i]);
fs[p] = -1;
sz[p] = 1;
for (edge* e = head[p]; e; e = e-> next)
if (fa[e-> t] == p) {
sz[p] += sz[e-> t];
if (fs[p] == -1 || sz[e-> t] > sz[fs[p]])
fs[p] = e-> t;
}
if (fs[p] == -1)
fc[p] = ++ tc;
else
fc[p] = fc[fs[p]];
ch[fc[p]] = p;
}
stc[tst = 1] = 1;
dfn = 0;
while (tst) {
int p(stc[tst --]);
dfo[++ dfn] = p;
dfb[p] = dfn;
for (edge* e = head[p]; e; e = e-> next)
if (fa[e-> t] == p && e-> t != fs[p])
stc[++ tst] = e-> t;
if (fs[p] != -1)
stc[++ tst] = fs[p];
}
rt = 0;
for (int i = 1; i <= n; ++ i)
rt = merge(rt, newNode(v[dfo[i]]));
remp = 0;
for (int i = 1; i <= n; ++ i)
remp = merge(remp, newNode(-1));
}
int query(int u, int v) {
int s(0);
while (fc[u] ^ fc[v])
if (d[ch[fc[u]]] > d[ch[fc[v]]]) {
s += smtQry(rt, dfb[u]) - smtQry(rt, dfb[ch[fc[u]]] - 1);
u = fa[ch[fc[u]]];
}
else {
s += smtQry(rt, dfb[v]) - smtQry(rt, dfb[ch[fc[v]]] - 1);
v = fa[ch[fc[v]]];
}
if (d[u] < d[v])
s += smtQry(rt, dfb[v]) - smtQry(rt, dfb[u] - 1);
else
s += smtQry(rt, dfb[u]) - smtQry(rt, dfb[v] - 1);
return s;
}
bool checkTree(node* p, char e) {
if (p) {
if (p-> rv) {
checkTree(p-> rs, 32);
printf("%d%c", p-> v, e);
checkTree(p-> ls, 32);
}
else {
checkTree(p-> ls, 32);
printf("%d%c", p-> v, e);
checkTree(p-> rs, 32);
}
}
return 0;
}
typedef pair <int, int> rpr;
rpr ra[maxn], rb[maxn];
void flip(int u, int v) {
int tra(0), trb(0);
while (fc[u] ^ fc[v]) {
if (d[ch[fc[u]]] > d[ch[fc[v]]]) {
ra[tra ++] = rpr(dfb[ch[fc[u]]], dfb[u]);
u = fa[ch[fc[u]]];
}
else {
rb[trb ++] = rpr(dfb[ch[fc[v]]], dfb[v]);
v = fa[ch[fc[v]]];
}
}
if (d[u] < d[v])
rb[trb ++] = rpr(dfb[u], dfb[v]);
else
ra[tra ++] = rpr(dfb[v], dfb[u]);
node *cr(0);
for (int i = 0; i < tra; ++ i) {
npr x = split(rt, ra[i]. first - 1);
npr y = split(x. second, ra[i]. second - ra[i]. first + 1);
cr = merge(y. first, cr);
npr z = split(remp, ra[i]. second - ra[i]. first + 1);
remp = z. second;
x. second = merge(z. first, y. second);
rt = merge(x. first, x. second);
}
if (cr)
cr-> rv ^= 1;
for (int i = trb - 1; i >= 0; -- i) {
npr x = split(rt, rb[i]. first - 1);
npr y = split(x. second, rb[i]. second - rb[i]. first + 1);
cr = merge(cr, y. first);
npr z = split(remp, rb[i]. second - rb[i]. first + 1);
remp = z. second;
x. second = merge(z. first, y. second);
rt = merge(x. first, x. second);
}
if (cr)
cr-> rv ^= 1;
for (int i = 0; i < tra; ++ i) {
npr x = split(rt, ra[i]. first - 1);
npr y = split(x. second, ra[i]. second - ra[i]. first + 1);
npr z = split(cr, ra[i]. second - ra[i]. first + 1);
cr = z. second;
if (z. first)
z. first-> rv ^= 1;
x. second = merge(z. first, y. second);
rt = merge(x. first, x. second);
remp = merge(remp, y. first);
}
if (cr)
cr-> rv ^= 1;
for (int i = 0; i < trb; ++ i) {
npr x = split(rt, rb[i]. first - 1);
npr y = split(x. second, rb[i]. second - rb[i]. first + 1);
npr z = split(cr, rb[i]. second - rb[i]. first + 1);
cr = z. second;
if (z. first)
z. first-> rv ^= 1;
x. second = merge(z. first, y. second);
rt = merge(x. first, x. second);
remp = merge(remp, y. first);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
memset(head, 0, sizeof(head));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i)
scanf("%d", v + i);
for (int i = 1; i < n; ++ i) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
divide();
while (m --) {
int opt, u, v;
scanf("%d%d%d", &opt, &u, &v);
if (opt == 0)
printf("%d\n", query(u, v));
else
flip(u, v);
}
}