1、题意:
2、分析:先来考虑那个最大路径是什么鬼。。一个环里面的点那么这个点都可以到对吧。。那就是缩环咯,这样就可以搞成一个树,缩环用并查集来做,每一次链接两个点,如果变成环就缩,不是就在树上玩,那么这个很显然可以使用lct+并查集来完成。
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <bitset>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define M 1000010
#define LL long long
#define MOD 1000000007
#define inf 2147483647
#define llinf 4000000000000000000ll
#define For(i, x, y) for(int i = (x); i < (y); i ++)
#define rep(i, x, y) for(int i = (x); i <= (y); i ++)
#define drep(i, x, y) for(int i = (x); i >= (y); i --)
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline LL llread(){
char ch=getchar();LL x=0,f=1;
while(ch<'0'||ch
>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct Union{
int fa[M];
inline void init(int n){
rep(i, 1, n) fa[i] = i;
}
inline int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
inline void merge(int x, int y){
int p = find(x), q = find(y);
if(p != q) fa[p] = q;
}
} aa, bb;
namespace LinkCutTree{
struct Node{
Node *ch[2], *fa;
int val, sum, num;
bool rev;
Node();
inline int which();
inline void reverse(){
if(this){
rev ^= 1;
swap(ch[0], ch[1]);
}
}
inline void pd(){
if(rev){
ch[0] -> reverse();
ch[1] -> reverse();
rev = 0;
}
}
inline void maintain(){
sum = ch[0] -> sum + ch[1] -> sum + val;
}
} *null, *pos[M], tree[M];
inline int Node::which(){
if(fa == null || (fa -> ch[0] != this && fa -> ch[1] != this)) return -1;
return fa -> ch[1] == this;
}
Node::Node(){
rev = false;
ch[0] = ch[1] = fa = null;
sum = val = num = 0;
}
inline void rotate(Node *o){
Node *p = o -> fa;
int l = o -> which(), r = l ^ 1;
o -> fa = p -> fa;
if(p -> which() != -1) p -> fa -> ch[p -> which()] = o;
p -> ch[l] = o -> ch[r];
if(o -> ch[r]) o -> ch[r] -> fa = p;
o -> ch[r] = p; p -> fa = o;
o -> ch[r] -> maintain();
o -> maintain();
}
inline void splay(Node *o){
static stack<Node*> st;
Node *p = o;
while(1){
st.push(p);
if(p -> which() == -1) break;
p = p -> fa;
}
while(!st.empty()){
st.top() -> pd(); st.pop();
}
while(o -> which() != -1){
p = o -> fa;
if(p -> which() != -1){
if(p -> which() ^ o -> which()) rotate(o);
else rotate(p);
}
rotate(o);
}
}
inline void Access(Node *o){
Node *y = null;
while(o != null){
splay(o);
o -> ch[1] = y;
o -> maintain();
y = o;
o -> fa = pos[bb.find(o -> fa -> num)];
o = o -> fa;
}
}
inline void MovetoRoot(Node *o){
Access(o);
splay(o);
o -> reverse();
}
inline void Link(Node *x, Node *y){
MovetoRoot(x);
x -> fa = y;
}
inline void Cut(Node *x, Node *y){
MovetoRoot(x);
Access(y);
splay(y);
y -> ch[0] = x -> fa = null;
y -> maintain();
}
inline void color(Node* &a, int b){
if(a == null) return;
if(a -> num != b){
pos[b] -> val += a -> val;
//a -> val = 0;
}
bb.merge(a -> num, b);
color(a -> ch[0], b);
color(a -> ch[1], b);
a -> maintain();
//a = null;
}
}
int value[M];
int main(){
//freopen("0input.in", "r", stdin);
using namespace LinkCutTree;
pos[0] = null = &tree[0];
int n = read(), m = read();
aa.init(n); bb.init(n);
rep(i, 0, n){
tree[i].ch[0] = null;
tree[i].ch[1] = null;
tree[i].fa = null;
}
rep(i, 1, n){
pos[i] = &tree[i];
value[i] = pos[i] -> val = read();
pos[i] -> maintain();
pos[i] -> num = i;
}
while(m --){
int p = read(), a = read(), b = read();
if(p == 1){
a = bb.find(a), b = bb.find(b);
if(aa.find(a) == aa.find(b)){
if(a == b) continue;
MovetoRoot(pos[b]);
Access(pos[a]);
splay(pos[a]);
color(pos[a], a);
}
else{
// puts("-1");
Link(pos[a], pos[b]);
aa.merge(a, b);
}
}
else if(p == 2){
int x = bb.find(a);
splay(pos[x]);
pos[x] -> val += b - value[a];
pos[x] -> maintain();
value[a] = b;
}
else{
a = bb.find(a), b = bb.find(b);
if(aa.find(a) != aa.find(b)){
puts("-1"); continue;
}
MovetoRoot(pos[b]);
Access(pos[a]);
splay(pos[a]);
printf("%d\n", pos[a] -> sum);
}
}
return 0;
}
作者:qzh_1430586275 发表于2017/1/1 16:57:49 原文链接
阅读:36 评论:0 查看评论