传送门:http://www.spoj.com/problems/OTOCI
(1)题意
给你n个结点以及每个结点对应的的权值wi。起始时,结点与结点之间没有连边。
有以下三类操作:
1、bridge A B:询问结点A与结点B是否连通。如果是,则输出“no”;否则,输出“yes”,并且在结点A和结点B之间连一条无向边;
2、penguins A X:将结点A对应的权值wA改为X;
3、excursion A B:如果结点A和结点B不连通,则输出“impossible”;否则,输出结点A到结点B的路径上的点对应的权值的和。
(2)模型
动态树的基本的查询,修改操作
(3)算法设计
splay + 树链剖分 + 维护思想
(4)数据结构
动态树 简单的查询和修改操作
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 60000;
struct LinkCutTree
{
private:
struct Node
{
int idx;
int total;
bool isRev;
int father,lch,rch,path_parent;
};
Node nodes[maxn];
int nodeCnt,location[maxn];
int data[maxn];
inline void normalize(int p)
{
if(nodes[p].isRev)
{
nodes[p].isRev = false;
nodes[nodes[p].lch].isRev = !nodes[nodes[p].lch].isRev;
nodes[nodes[p].rch].isRev = !nodes[nodes[p].rch].isRev;
swap(nodes[p].lch,nodes[p].rch);
}
nodes[p].total = nodes[nodes[p].lch].total + nodes[nodes[p].rch].total + data[nodes[p].idx];
}
void leftrotate(int x)
{
int y = nodes[x].father;
nodes[x].path_parent = nodes[y].path_parent;
nodes[y].path_parent = 0;
nodes[y].rch = nodes[x].lch;
int tmp = nodes[y].total;
nodes[y].total = nodes[y].total - nodes[x].total +nodes[nodes[x].lch].total;
nodes[x].total = tmp;
if(nodes[x].lch)
nodes[nodes[x].lch].father = y;
nodes[x].father = nodes[y].father;
if(nodes[y].father)
{
if(y == nodes[nodes[y].father].lch)
nodes[nodes[y].father].lch = x;
else
nodes[nodes[y].father].rch = x;
}
nodes[y].father = x;
nodes[x].lch = y;
}
void rightrotate(int x)
{
int y = nodes[x].father;
nodes[x].path_parent = nodes[y].path_parent;
nodes[y].path_parent = 0;
nodes[y].lch = nodes[x].rch;
int tmp = nodes[y].total;
nodes[y].total = nodes[y].total - nodes[x].total + nodes[nodes[x].rch].total;
nodes[x].total = tmp;
if(nodes[x].rch)
nodes[nodes[x].rch].father = y;
nodes[x].father = nodes[y].father;
if(nodes[y].father)
{
if(y == nodes[nodes[y].father].lch)
nodes[nodes[y].father].lch = x;
else
nodes[nodes[y].father].rch = x;
}
nodes[y].father = x;
nodes[x].rch = y;
}
void splay(int x)
{
while(nodes[x].father)
{
int father = nodes[x].father;
normalize(nodes[x].father);
if(nodes[father].lch)
normalize(nodes[father].lch);
if(nodes[father].rch)
normalize(nodes[father].rch);
if(x==nodes[nodes[x].father].lch)
rightrotate(x);
else
leftrotate(x);
}
}
void Access(int p)
{
splay(p);
normalize(p);
int q=nodes[p].rch;
nodes[p].rch = nodes[q].father = 0;
nodes[q].path_parent = p;
normalize(p);
for(q = nodes[p].path_parent;q;q=nodes[p].path_parent)
{
splay(q);
normalize(q);
int r = nodes[q].rch;
nodes[r].father = 0;
nodes[r].path_parent = q;
nodes[q].rch = p;
nodes[p].father = q;
nodes[p].path_parent = 0;
normalize(q);
p = q;
}
splay(p);
}
int Find_Root(int p)
{
Access(p);
splay(p);
normalize(p);
while(nodes[p].lch)
p = nodes[p].lch;
splay(p);
return p;
}
void Evert(int p)
{
Access(p);
splay(p);
nodes[p].isRev = !nodes[p].isRev;
normalize(p);
}
void Cut(int p,int q)
{
Evert(p);
Access(q);
splay(q);
normalize(q);
nodes[nodes[q].lch].father = 0;
nodes[q].lch = 0;
normalize(q);
}
void Link(int p,int q)
{
Evert(p);
splay(p);
normalize(p);
Access(q);
splay(q);
normalize(q);
nodes[p].lch = q;
nodes[q].father = p;
normalize(p);
}
int Sum(int p,int q)
{
Evert(p);
splay(p);
normalize(p);
Access(q);
splay(q);
normalize(q);
return nodes[q].total;
}
void Change(int p,int d,int pre)
{
splay(p);
nodes[p].total += d-pre;
}
public:
void init()
{
nodeCnt = 0;
memset(location,0,sizeof(location));
nodes[0].total = 0;
}
void Make_Tree(int idx,int d)
{
data[idx] = d;
int p = ++nodeCnt;
location[idx] = p;
nodes[p].father = nodes[p].lch = nodes[p].rch = nodes[p].path_parent = 0;
nodes[p].total = data[idx];
nodes[p].idx = idx;
}
int getRoot(int idx)
{
return nodes[Find_Root(idx)].idx;
}
void addEdge(int x,int y)
{
Link(location[x],location[y]);
}
void destroy(int x,int y)
{
Cut(location[x],location[y]);
}
int getSum(int x,int y)
{
return Sum(location[x],location[y]);
}
void change(int x,int d)
{
Change(location[x],d,data[x]);
data[x] = d;
}
};
LinkCutTree T;
int main()
{
int n;
scanf("%d",&n);
T.init();
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
T.Make_Tree(i,k);
}
int q;
scanf("%d",&q);
while(q--)
{
char cmd[20];
int x,y;
scanf("%s",cmd);
scanf("%d %d",&x,&y);
if(cmd[0] == 'b')
{
if(T.getRoot(x)==T.getRoot(y))
printf("no\n");
else
{
printf("yes\n");
T.addEdge(x,y);
}
}
else if(cmd[0] == 'p')
{
T.change(x,y);
}
else if(cmd[0] == 'e')
{
if(T.getRoot(x)!=T.getRoot(y))
printf("impossible\n");
else
printf("%d\n",T.getSum(x,y));
}
else
printf("scanning is wrong!\n");
}
return 0;
}