1180: [CROATIAN2009]OTOCI(LCT)

1180: [CROATIAN2009]OTOCI

Time Limit: 50 Sec  Memory Limit: 162 MB
Submit: 1200  Solved: 747
[Submit][Status][Discuss]

Description

给出n个结点以及每个点初始时对应的权值wi。起始时点与点之间没有连边。有3类操作: 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的路径上的点对应的权值的和。给出q个操作,要求在线处理所有操作。数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

Input

第一行包含一个整数n(1<=n<=30000),表示节点的数目。第二行包含n个整数,第i个整数表示第i个节点初始时对应的权值。第三行包含一个整数q(1<=n<=300000),表示操作的数目。以下q行,每行包含一个操作,操作的类别见题目描述。任意时刻每个节点对应的权值都是1到1000的整数。

Output

输出所有bridge操作和excursion操作对应的输出,每个一行。

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

code

 1 #include<cstdio>
 2 #include<algorithm>
 3
 4 using namespace std;
 5
 6 const int N = 50010;
 7
 8 int val[N],fa[N],ch[N][2],rev[N],sum[N],st[N],top;
 9
10 void pushup(int x) {
11     sum[x] = sum[ch[x][1]] + sum[ch[x][0]] + val[x];
12 }
13 void pushdown(int x) {
14     int l = ch[x][0],r = ch[x][1];
15     if (rev[x]) {
16         rev[l] ^= 1;rev[r] ^= 1;
17         swap(ch[x][0],ch[x][1]);
18         rev[x] ^= 1;
19     }
20 }
21 bool isroot(int x) {
22     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
23 }
24 int son(int x) {
25     return ch[fa[x]][1]==x;
26 }
27 void rotate(int x) {
28     int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b];
29     if (!isroot(y)) ch[z][c] = x;fa[x] = z;
30     ch[x][!b] = y;fa[y] = x;
31     ch[y][b] = a;if (a) fa[a] = y;
32     pushup(y);pushup(x);
33 }
34 void splay(int x) {
35     top = 0;st[++top] = x;
36     for (int i=x; !isroot(i); i=fa[i]) st[++top] = fa[i];
37     while (top) pushdown(st[top--]);
38     while (!isroot(x)) {
39         int y = fa[x];
40         if (!isroot(y)) {
41             if (son(x)==son(y)) rotate(y);
42             else rotate(x);
43         }
44         rotate(x);
45     }
46 }
47 void access(int x) {
48     for (int t=0; x; t=x,x=fa[x]) {
49         splay(x);ch[x][1] = t;pushup(x);
50     }
51 }
52 void makeroot(int x) {
53     access(x);
54     splay(x);
55     rev[x] ^= 1;
56 }
57 void link(int x,int y) {
58     makeroot(x);
59     fa[x] = y;
60 }
61 void update(int x,int y) {
62     makeroot(x);val[x] = y;pushup(x);
63 }
64 int query(int x,int y) {
65     makeroot(x);access(y);splay(y);
66     return sum[y];
67 }
68 int find(int x) {
69     access(x);splay(x);
70     while (ch[x][0]) x = ch[x][0];
71     return x;
72 }
73 int main() {
74     int n,m,x,y;
75     char opt[20];
76     scanf("%d",&n);
77     for (int i=1; i<=n; ++i) scanf("%d",&val[i]),sum[i] = val[i];
78     scanf("%d",&m);
79     while (m--) {
80         scanf("%s%d%d",opt,&x,&y);
81         if (opt[0]==‘b‘) {
82             if (find(x)==find(y)) puts("no");
83             else puts("yes"),link(x,y);
84         }
85         else if (opt[0]==‘p‘) update(x,y);
86         else {
87             if (find(x)!=find(y)) puts("impossible");
88             else printf("%d\n",query(x,y));
89         }
90     }
91     return 0;
92 }

原文地址:https://www.cnblogs.com/mjtcn/p/8150398.html

时间: 2024-10-10 09:03:21

1180: [CROATIAN2009]OTOCI(LCT)的相关文章

【BZOJ】1180: [CROATIAN2009]OTOCI(lct)

http://www.lydsy.com/JudgeOnline/problem.php?id=1180 今天状态怎么这么不好....................................... 又是调了好久........................................... 我竟然忘记更改值那里要先makeroot后再更改,而且还要pushup先!!!!! QAQ 太弱了.. 记住!!!更改信息一定要先变成了根再修改,而且还要pushup! #include <cs

BZOJ 1180: [CROATIAN2009]OTOCI [LCT]

1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 961  Solved: 594[Submit][Status][Discuss] Description 给出n个结点以及每个点初始时对应的权值wi.起始时点与点之间没有连边.有3类操作: 1.bridge A B:询问结点A与结点B是否连通.如果是则输出“no”.否则输出“yes”,并且在结点A和结点B之间连一条无向边. 2.penguins A

【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)

(BZOJ挂了,还没在BZOJ测,先是在wikioi测过了,,) 囧.在军训时立志要学lct!!!这是一道lct的裸题,只有access操作(10行都没有啊亲...缩行大法的话,我就不说了..)(link操作相当于水过),其实lct很简单..想想都有点小激动...... lct用splay维护的话,一下就写好了..但是我在写lct的时候,发现了一些我原来splay的老问题,我原来也知道了的,就是将null的ch给赋值了,因为在rot操作里没有特判,所以导致了null的孩子被赋值了,导致我的lct

从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)

[首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以像树链剖分一样对树上的两点进行询问(权值和.权值的最值……),还可以维护森林的连通性. 学习LCT首推杨哲神犇的<QTREE解法的一些研究>,很详细地解释了LCT的概念及实现 本文则以ZOJ2114一题为例,分析LCT实现过程中的一些事项,并且力求读者对LCT有一个“不次于‘感性’的认识” 叙述过程中会直接引用论文中的术

【BZOJ】3669: [Noi2014]魔法森林(lct)

http://www.lydsy.com/JudgeOnline/problem.php?id=3669 首先看到题目应该可以得到我们要最小化 min{ max{a(u, v)} + max{b(u, v)} } 两个变量不好做...那么我们约束一个a 即按a从小到大排序,依次加边. 发现当有环出现时,去掉的是环中b最大的边. 证明:因为a是从小到大排序,因此此时答案为 a+max{b(u, v)},显然b越小越好. 然后需要link和cut操作... 脑洞开到这里开不动了...........

关于树论【动态树问题(LCT)】

搬运:看一道caioj1439 题目描述 一开始给你一棵n个点n-1条边的树,每个点有一个权值wi. 三种操作: op=1 u v :在点u和点v之间建一条边. op=2 u v:摧毁点u到点v之间的边. op=3 w u v:将点u和点v之间路径上的点(包括u,v),权值增加w. op=4 u v:询问点u到点v之间路径上的点(包括u,v),权值最大值. 当操作违法时(询问一中u,v已经相连,二三四中u,v不联通,一二操作u==v)不进行操作并输出-1. 输入 从文件weight.in中读取输

BZOJ 3282 Tree(LCT)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3282 [题目大意] 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点X上的权值变成Y. [题解] LCT练习题 [代码] #include <cstdi

SP2666 QTREE4 - Query on a tree IV(LCT)

题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下操作: C a 将点a的颜色反转(黑变白,白变黑) A 询问dist(a,b)的最大值.a,b点都必须为白色(a与b可以相同),显然如果树上仍存在白点,查询得到的值一定是个非负数. 特别地,如果作'A'操作时树上没有白点,输出"They have disappeared.". 题解 一道神

P3379 【模板】最近公共祖先(LCA)(LCT)

\(\color{#0066ff}{ 题目描述 }\) 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. \(\color{#0066ff}{输入格式}\) 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. \(\color{#0066ff}{输出格式}\) 输出包含M