bzoj1180: [CROATIAN2009]OTOCI

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

题解:

  LCT模板题·····练手用的······

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 char ch; bool ok;
 8 void read(int &x){
 9     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
10     for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
11     if (ok) x=-x;
12 }
13 const int maxn=100005;
14 int n,q,x,y;
15 char op[10];
16 struct LCT{
17     #define ls son[x][0]
18     #define rs son[x][1]
19     int fa[maxn],son[maxn][2],rev[maxn],val[maxn],sum[maxn];
20     int which(int x){return son[fa[x]][1]==x;}
21     bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
22     void addtag_rev(int x){if (x) rev[x]^=1,swap(ls,rs);}
23     void pushdown(int x){if (rev[x]) addtag_rev(ls),addtag_rev(rs),rev[x]=0;}
24     void relax(int x){
25         if (!isroot(x)) relax(fa[x]);
26         pushdown(x);
27     }
28     void updata(int x){sum[x]=sum[ls]+val[x]+sum[rs];}
29     void rotate(int x){
30         int y=fa[x],z=fa[y],d=which(x),dd=which(y);
31         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=fa[y];
32         if (!isroot(y)) son[z][dd]=x;
33         son[x][d^1]=y,fa[y]=x,updata(y);
34     }
35     void splay(int x){
36         relax(x);
37         while (!isroot(x)){
38             if (isroot(fa[x])) rotate(x);
39             else if (which(fa[x])==which(x)) rotate(fa[x]),rotate(x);
40             else rotate(x),rotate(x);
41         }
42         updata(x);
43     }
44     void access(int x){for (int p=0;x;x=fa[x]) splay(x),son[x][1]=p,p=x;}
45     void make_root(int x){access(x),splay(x),addtag_rev(x);}
46     void connect(int u,int v){make_root(u),fa[u]=v;}
47     int query_sum(int u,int v){make_root(u),access(v),splay(v);return sum[v];}
48     int find_left(int x){for (pushdown(x);son[x][0];x=son[x][0],pushdown(x));return x;}
49     bool query_con(int u,int v){make_root(u),access(v),splay(v);return find_left(v)==u;}
50     void modify(int x,int v){val[x]=sum[x]=v,splay(x);}
51 }T;
52 int main(){
53     read(n);
54     for (int i=1;i<=n;i++) read(x),T.modify(i,x);
55     for (read(q);q;q--){
56         scanf("%s",op+1),read(x),read(y);
57         if (op[1]==‘b‘){
58             if (T.query_con(x,y)) puts("no");
59             else T.connect(x,y),puts("yes");
60         }
61         else if (op[1]==‘p‘) T.modify(x,y);
62         else if (op[1]==‘e‘){
63             if (T.query_con(x,y)) printf("%d\n",T.query_sum(x,y));
64             else puts("impossible");
65         }
66     }
67     return 0;
68 }
时间: 2024-11-08 17:29:29

bzoj1180: [CROATIAN2009]OTOCI的相关文章

[bzoj1180][CROATIAN2009]OTOCI_LCT

OTOCI bzoj-1180 CROATIAN-2009 题目大意:给你n个离散的点,m个操作.支持:两点加边(保证还是森林),修改单点权值,询问两点是否联通,查询联通两点之间路径权值. 注释:$1\le n \le 30,000$,$1\le m \le 300,000$. 想法:显然,又是一道LCT裸题.加边操作直接用link,修改权值直接修改,路径和的话每个点维护子树权值和makeroot(x)+access(y)+splay(y),然后直接查询子树和即可. 最后,附上丑陋的代码...

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

1180: [CROATIAN2009]OTOCI(LCT)

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

【bzoj1180】[CROATIAN2009]OTOCI LCT

题目描述 给出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个操作,要

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

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

bzoj 1180: [CROATIAN2009]OTOCI

http://www.lydsy.com/JudgeOnline/problem.php?id=1180 大约又是个裸的lct,开始re了好久后来发现建了重边 #include<cstdio> #include<iostream> const int maxn =60007; int n,m; int top=0; int ch[maxn][2],fa[maxn],stack[maxn]; int ans[maxn],v[maxn]; bool rev[maxn]; inline

对于动态树 (Link-Cut-Tree, LCT) 的理解与总结

原文链接http://www.cnblogs.com/zhouzhendong/p/8424570.html 对于动态树 $(Link-Cut-Tree, LCT)$ 的理解与总结 问题模型 有$n$个节点,每个节点有权值$v_i$,现在有$m$个操作,操作有可能是以下$4$种类型: $1$   -   连接两个节点 $2$   -   断开两个节点之间的边 $3$   -   修改某一个节点的权值 $4$   -   询问两点之间的节点权值和 保证操作和询问合法,并且输入数据保证任何时刻图中不

bzoj1180,2843

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

【算法总结】树相关

[点分治] [模板代码] 1 void getroot(int x,int fa) 2 { 3 sz[x]=1;mx[x]=0; 4 for(int i=first[x];i;i=e[i].next) 5 { 6 int to=e[i].to; 7 if(to==fa||vis[to])continue; 8 getroot(to,x); 9 sz[x]+=sz[to]; 10 mx[x]=max(mx[x],sz[to]); 11 } 12 mx[x]=max(mx[x],sum-sz[x])