您的位置:首页 > 运维架构

UOJ #207. 共价大爷游长沙(不用维护子树的LCT)

2018-03-26 22:24 441 查看

传送门

题目大意:自己看题目吧。。

思路

这题真是机巧。

为每一条路径随机一个权值,记录每条边上的异或值。对于一条删边,将其权值异或到新的路径上,用LCT维护。

判断一条边是否被所有路径经过只用判断异或和是否相等就行了。

中间要用map等小技巧,还是比较简单的,不用维护任何东西。但是难想。第一次写随机数冲突了,srand(num)比较可行。还有就是每次询问之前别忘了splay一下。

还有一种维护子树异或和的做法,这里就不讲了。(这也是基础的操作啊)

推荐去看kekxy的博客。

代码

#include <bits/stdc++.h>
#define maxn 200010
#define M1 998244353
#define M2 1000000007
#define M3 1333333331

using namespace std;

int ID, cnt, n, m, ToT, VAL;
map <long long, int> M;
int X[maxn], Y[maxn], Z[maxn];

struct Tnode{
Tnode *son[2], *fa;
int parent, val, add;
bool rev;
int Get_d(){return fa->son[1] == this;}
void Connect(Tnode *now, int d){(son[d] = now)->fa = this;}
void Down(){
if(rev){
swap(son[0], son[1]);
if(son[0])  son[0]->rev ^= 1;
if(son[1])  son[1]->rev ^= 1;
rev = false;
}
if(add){
if(son[0])  son[0]->val ^= add, son[0]->add ^= add;
if(son[1])  son[1]->val ^= add, son[1]->add ^= add;
add = 0;
}
}
}tree[maxn], *Node[maxn];

Tnode *NewTnode(){
tree[cnt].fa = tree[cnt].son[0] = tree[cnt].son[1] = NULL;
tree[cnt].parent = tree[cnt].add = 0;
tree[cnt].rev = false;
return tree+cnt++;
}

void Zig(Tnode *now){
Tnode *last = now->fa;
int d = now->Get_d();
if(now->son[!d])  last->Connect(now->son[!d], d);
else  last->son[d] = NULL;
if(last->fa)  last->fa->Connect(now, last->Get_d());
else  now->fa = NULL;
now->Connect(last, !d);
now->parent = last->parent;
last->parent = 0;
}

void Splay(Tnode *now){
Tnode *last;
while(now->fa){
last = now->fa;
if(last->fa)  last->fa->Down();
last->Down();  now->Down();
if(last->fa)  (now->Get_d() ^ last->Get_d()) ? Zig(now) : Zig(last);
Zig(now);
}
if(!now->fa)  now->Down();
}

void Access(int x){

Splay(Node[x]);
if(Node[x]->son[1]){
Node[x]->son[1]->fa = NULL;
Node[x]->son[1]->parent = x;
Node[x]->son[1] = NULL;
}

int y = Node[x]->parent;
while(y){
Splay(Node[y]);
if(Node[y]->son[1]){
Node[y]->son[1]->fa = NULL;
Node[y]->son[1]->parent = y;
Node[y]->son[1] = NULL;
}
Node[y]->Connect(Node[x], 1
f575
);
Node[x]->parent = 0;

x = y;
y = Node[x]->parent;
}
}

void Evert(int x){
Access(x);
Splay(Node[x]);
Node[x]->rev ^= 1;
}

void Link(int x, int y){
Evert(x);
Node[x]->parent = y;
}

void Cut(int x, int y){
Evert(x);
Access(y);
Splay(Node[x]);
Node[x]->son[1]->fa = NULL;
Node[x]->son[1] = NULL;
}

void Update(int x, int y, int val){
Evert(x);
Access(y);
Splay(Node[x]);
Node[x]->val ^= val;
Node[x]->add ^= val;
}

int Query(int x, int y){
int edge = M[1LL*x*(n-1)+y];
Splay(Node[edge]);
return Node[edge]->val;
}

int Get(){
VAL = (1LL * VAL * M1 + M2) % M3;
return VAL;
}

int main(){

scanf("%d", &ID);

scanf("%d%d", &n, &m);

for(int i = 1; i <= n; i++)  Node[i] = NewTnode();

int a, b;
for(int i = 1; i < n; i++){
Node[i+n] = NewTnode();
scanf("%d%d", &a, &b);
M[1LL*a*(n-1)+b] = M[1LL*b*(n-1)+a] = i + n;
Link(a, i+n);
Link(i+n, b);
}

int op, u, v;
for(int i = 1; i <= m; i++){
scanf("%d", &op);
if(op == 1){
scanf("%d%d%d%d", &a, &b, &u, &v);

int edge = M[1LL*a*(n-1)+b];
Splay(Node[edge]);
int val = Node[edge]->val;
Cut(a, edge);
Cut(edge, b);

Node[edge]->fa = Node[edge]->son[0] = Node[edge]->son[1] = NULL;
Node[edge]->val = Node[edge]->parent = 0;
Node[edge]->rev = false;

Link(u, edge);
Link(edge, v);
M[1LL*u*(n-1)+v] = M[1LL*v*(n-1)+u] = edge;
Update(a, b, val);
}
else if(op == 2){
scanf("%d%d", &a, &b);
int val = Get();
ToT ^= val;
Update(a, b, val);
X[++X[0]] = a;  Y[X[0]] = b;  Z[X[0]] = val;
}
else if(op == 3){
scanf("%d", &a);
ToT ^= Z[a];
Update(X[a], Y[a], Z[a]);
}
else{
scanf("%d%d", &a, &b);
int res = Query(a, b);
if(res == ToT)  puts("YES");
else  puts("NO");
}
}

return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: