https://www.lydsy.com/JudgeOnline/problem.php?id=2959
这个垃圾题目我再也不想做了!!!!!!!!!
不但难调还卡常 真的毒瘤 还有实名diss
bzoj
b
z
o
j
垃圾评测机 交darkbzoj才过的
这个题就发现双联通分量里的点都可以互相到达
每次加边判断连通性
如果已经联通就用并查集缩环为一点
把点权全部加起来即可
虽然讲起来很简单 但是这个题真的很难调啊啊
notice
任何调用 fa f a 数组的时候都要 记得找并查集里的 包括 isroot i s r o o t 和 rel r e l
不想写了 上代码
Cdoes
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define FOR(i, a, b) for(register int i = a; i >= b; -- i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
using namespace std;
const int N = 3e5 + 10;
int be[N], fa2[N], v[N];
int n, m;
inline int Belong(int x) {
if(be[x] == x) return x;
return be[x] = Belong(be[x]);
}
inline int Find(int x) {
if(fa2[x] == x) return x;
return fa2[x] = Find(fa2[x]);
}
namespace In {
# define In_Len 100000000
static std :: streambuf* fb ( std :: cin.rdbuf ( ) ) ;
static char buf [In_Len], *ss ( 0 ) ;
void init ( ) { fb -> sgetn ( ss = buf, In_Len ) ; }
inline int read ( ) {
register int x ;
bool opt ( 1 ) ;
while ( isspace ( *ss ) ) ++ ss ;
if ( *ss == 45 ) { ++ ss ; opt = 0 ; }
for ( x = -48 + *ss ; isdigit ( * ++ ss ) ; ( x *= 10 ) += *ss - 48 ) ; ++ ss ;
return opt ? x : -x ;
}
# undef In_Len
}
namespace Out {
# define Out_Len 100000000
static std :: streambuf* fb ( std :: cout.rdbuf ( ) ) ;
static char buf [Out_Len], *ss ( buf ) ;
inline void print ( register int x ) {
static int T [30], tp ( 0 ) ;
if ( ! x ) { *ss ++ = 48 ; *ss ++ = 10 ; return ; }
if ( x < 0 ) { *ss ++ = 45 ; x = -x ; }
while ( x ) T [++ tp] = x % 10 | 48, x /= 10 ;
while ( tp ) *ss ++ = T [tp --] ;
*ss ++ = 10 ;
}
inline void flush ( ) { fb -> sputn ( buf, ss - buf ) ; }
# undef Out_Len
}
struct Link_Cut_Tree {
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
#define rel(x) (x == rs(Fa(x)))
#define Fa(x) (Belong(fa[x]))
int fa[N], ch[N][2], sum[N], val[N], rev[N], Sta[N], top;
bool isroot(int x) {
return ls(Fa(x)) != x && rs(Fa(x)) != x;
}
void reverse(int x) {
swap(ls(x), rs(x));
rev[x] ^= 1;
}
void pushup(int x) {
sum[x] = sum[ls(x)] + sum[rs(x)] + val[x];
}
void pushdown(int x) {
if(rev[x]) {
if(ls(x)) reverse(ls(x));
if(rs(x)) reverse(rs(x));
rev[x] ^= 1;
}
}
void rotate(int x) {
int dad = Fa(x), f = rel(x);
if(!isroot(dad))
ch[Fa(dad)][rel(dad)] = x;
fa[x] = Fa(dad);
ch[dad][f] = ch[x][f ^ 1];
ch[x][f ^ 1] = dad;
fa[ch[dad][f]] = dad;
fa[dad] = x;
pushup(dad), pushup(x);
}
void splay(int x) {
top = 0;
for(register int i = x; i; i = Fa(i))
Sta[++ top] = i;
FOR(i, top, 1)
pushdown(Sta[i]);
while(!isroot(x))
rotate(x);
}
void access(int x) {
for(int y = 0; x; x = Fa(y = x))
splay(x), rs(x) = y, pushup(x);
}
void makeroot(int x) {
access(x); splay(x); reverse(x);
}
void split(int x, int y) {
makeroot(x); access(y); splay(y);
}
void merge(int x, int y) {
be[x] = y;
if(x != y) val[y] += val[x];
if(ls(x)) merge(ls(x), y);
if(rs(x)) merge(rs(x), y);
//ls(x) = rs(x) = 0;
}
void link(int x, int y) {
if(Find(x) != Find(y)) {
if(rand() & 2) {
makeroot(y);
//cerr << x << ' ' << y << endl;
fa[y] = x;
}
else {
makeroot(x);
fa[x] = y;
}
}
else {
split(x, y);
merge(y, y);
}
}
} T;
void File() {
#ifndef ONLINE_JUDGE
freopen("2959.in", "r", stdin);
freopen("2959.out", "w", stdout);
#endif
}
void Init() {
In::init();
n = In::read(), m = In::read();
for(int i = 1; i + 1 <= n; i += 2) {
v[i] = In::read(); v[i + 1] = In::read();
T.val[i] = v[i]; T.val[i + 1] = v[i + 1];
be[i] = fa2[i] = i; be[i + 1] = fa2[i + 1] = i + 1;
}
if(n & 1) {
v[n] = In::read();
T.val[n] = v[n];
be[n] = fa2[n] = n;
}
}
void Solve() {
int x, y, z;
For(i, 1, m) {
x = In::read(), y = In::read(), z = In::read();
// cerr << i << ' ' << x << ' ' << y << ' ' << z << endl;
if(x == 1) {
int fuck = Belong(y), fk = Belong(z);
if(fuck == fk)
continue;
T.link(fuck, fk);
fa2[Find(y)] = Find(z);
}
if(x == 2) {
int fuck = Belong(y);
T.makeroot(fuck);
T.val[fuck] += (z - v[y]);
T.pushup(fuck);
v[y] = z;
}
if(x == 3) {
if(Find(y) != Find(z))
Out::print(-1);
else {
int fuck = Belong(y), fk = Belong(z);
T.split(fuck, fk);
Out::print(T.sum[fk]);
}
}
}
Out::flush();
//cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
}
int main() {
File();
Init();
Solve();
return 0;
}