版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/80109312
Description
你的程序需要处理以下三种命令:
1.”bridge A B”——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当
A与B不联通。若这项命令被接受,你的程序需要输出”yes”,之
后会建造这座大桥。否则,你的程序需要输出”no”。
2.”penguins A X”——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不
需要回应。
3.”excursion A B”——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的
帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出”impossible”。
Sample Input
5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5
bridge 1 3
excursion 2 4
excursion 2 5
Sample Output
4
impossible
yes
6
yes
yes
15
yes
15
16
这道题LCT版题。
好像还可以离线做,改日来水。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int _max(int x, int y) {return x > y ? x : y;}
struct node {
int f, s, d, lazy, son[2];
} t[310000];
int tp, temp[310000];
char ss[11];
void Lazy(int x) {
if(!t[x].lazy) return ;
t[x].lazy = 0;
swap(t[x].son[0], t[x].son[1]);
int lc = t[x].son[0], rc = t[x].son[1];
if(lc) t[lc].lazy ^= 1;
if(rc) t[rc].lazy ^= 1;
}
void update(int x) {
int lc = t[x].son[0], rc = t[x].son[1];
t[x].s = t[x].d + t[lc].s + t[rc].s;
}
void rotate(int x, int fx) {
int f = t[x].f, ff = t[f].f;
int r, R;
r = t[x].son[fx], R = f;
if(r) t[r].f = R;
t[R].son[1 ^ fx] = r;
r = x, R = ff;
t[r].f = R;
if(t[ff].son[0] == f) t[R].son[0] = r; else if(t[ff].son[1] == f) t[R].son[1] = r;
r = f, R = x;
t[r].f = R;
t[R].son[fx] = r;
update(f);
update(x);
}
bool hh(int x) {
int f = t[x].f;
if(f == 0 || (t[f].son[0] != x && t[f].son[1] != x)) return 0;
return 1;
}
void splay(int x) {
int i = x; tp = 0;
while(hh(i)) temp[++tp] = i, i = t[i].f;
temp[++tp] = i;
for(int i = tp; i >= 1; i--) Lazy(temp[i]);
while(hh(x)) {
int f = t[x].f, ff = t[f].f;
if(!hh(f)) {
if(t[f].son[0] == x) rotate(x, 1);
else rotate(x, 0);
}
else if(t[ff].son[0] == f && t[f].son[0] == x) rotate(f, 1), rotate(x, 1);
else if(t[ff].son[0] == f && t[f].son[1] == x) rotate(x, 0), rotate(x, 1);
else if(t[ff].son[1] == f && t[f].son[1] == x) rotate(f, 0), rotate(x, 0);
else if(t[ff].son[1] == f && t[f].son[0] == x) rotate(x, 1), rotate(x, 0);
}
}
void Access(int x) {
int y = 0;
while(x) {
splay(x);
t[x].son[1] = y;
if(y) t[y].f = x;
update(x);
y = x; x = t[x].f;
}
}
void Makert(int x) {
Access(x); splay(x);
t[x].lazy ^= 1;
}
void Link(int x, int y) {
Makert(x); t[x].f = y; Access(x);
}
int Findrt(int x) {
Access(x); splay(x);
while(t[x].son[0]) x = t[x].son[0];
return x;
}
int finds(int x, int y) {
Makert(x);
Access(y); splay(y);
return t[y].s;
}
int main() {
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int x; scanf("%d", &x);
t[i].d = t[i].s = x;
}
int m; scanf("%d", &m);
for(int i = 1; i <= m; i++) {
scanf("%s", ss + 1);
int x, y; scanf("%d%d", &x, &y);
if(ss[1] == 'b') {
if(Findrt(x) == Findrt(y)) {
printf("no\n");
continue;
}
else printf("yes\n");
Link(x, y);
}
else if(ss[1] == 'p') {
Makert(x);
t[x].d = y;
update(x);
}
else {
if(Findrt(x) != Findrt(y)) {
printf("impossible\n");
continue;
}
printf("%d\n", finds(x, y));
}
}
return 0;
}
我来补离线水法啦。
因为你如果联通,肯定s值是固定的。
于是你先建出树,离线搞一下。
树状数组维护一下,并查集判一下联通。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct edge {
int x, y, next;
} e[61000]; int len, last[31000];
struct node {
int opt, x, y;
} b[110000];
int f[31000], a[31000], s[31000], dep[31000], fa[31000][18];
int n, id, ll[31000], rr[31000];
bool v[31000];
char ss[11];
int lowbit(int x) {return x & -x;}
void change(int x, int c) {
for(int i = x; i <= n; i += lowbit(i)) s[i] += c;
}
int getsum(int x) {
int sum = 0;
for(int i = x; i >= 1; i -= lowbit(i)) sum += s[i];
return sum;
}
void ins(int x, int y) {
e[++len].x = x; e[len].y = y;
e[len].next = last[x]; last[x] = len;
}
int findfa(int x) {
if(f[x] != x) f[x] = findfa(f[x]);
return f[x];
}
void dfs(int x) {
ll[x] = ++id;
v[x] = 1;
for(int i = 1; i <= 16; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(int k = last[x]; k; k = e[k].next) {
int y = e[k].y;
if(y != fa[x][0]) {
fa[y][0] = x;
dep[y] = dep[x] + 1;
dfs(y);
}
} rr[x] = id;
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 16; i >= 0; i--)
if(dep[x] - dep[y] >= (1 << i))
x = fa[x][i];
if(x == y) return x;
for(int i = 16; i >= 0; i--)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), f[i] = i;
int m; scanf("%d", &m);
for(int i = 1; i <= m; i++) {
scanf("%s", ss + 1);
scanf("%d%d", &b[i].x, &b[i].y);
if(ss[1] == 'b') {
int fx = findfa(b[i].x), fy = findfa(b[i].y);
if(fx != fy) {
f[fx] = fy;
ins(b[i].x, b[i].y); ins(b[i].y, b[i].x);
}
b[i].opt = 1;
}
else if(ss[1] == 'p') b[i].opt = 2;
else b[i].opt = 3;
}
for(int i = 1; i <= n; i++)
if(!v[i]) dfs(i);
for(int i = 1; i <= n; i++) f[i] = i, change(ll[i], a[i]), change(rr[i] + 1, -a[i]);
for(int i = 1; i <= m; i++) {
if(b[i].opt == 1) {
int fx = findfa(b[i].x), fy = findfa(b[i].y);
if(fx != fy) {
f[fx] = fy;
printf("yes\n");
}
else printf("no\n");
}
else if(b[i].opt == 2) {
change(ll[b[i].x], b[i].y - a[b[i].x]);
change(rr[b[i].x] + 1, a[b[i].x] - b[i].y);
a[b[i].x] = b[i].y;
}
else {
int fx = findfa(b[i].x), fy = findfa(b[i].y);
if(fx == fy) {
int lca = LCA(b[i].x, b[i].y);
int ss = getsum(ll[b[i].x]) + getsum(ll[b[i].y]);
ss -= getsum(ll[lca]) + getsum(ll[fa[lca][0]]);
printf("%d\n", ss);
}
else printf("impossible\n");
}
}
return 0;
}