【bzoj1180】[CROATIAN2009]OTOCI

xiaoxiao2021-02-28  104

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模板题 代码

#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #define ll long long int sum[30005],v[30005],fa[30005],c[30005][2],rev[30005],st[30005]; int n,q; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void update(int x) { sum[x]=sum[c[x][0]]+sum[c[x][1]]+v[x]; } void pushdown(int x) { if (rev[x]) { int l=c[x][0],r=c[x][1]; rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(c[x][0],c[x][1]); } } void rotate(int x) { int l,r,y=fa[x],z=fa[y]; if (c[y][0]==x) l=0;else l=1;r=l^1; if(!isroot(y)) { if (c[z][0]==y) c[z][0]=x;else c[z][1]=x; } fa[x]=z;fa[y]=x; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; update(y);update(x); } void splay(int x) { int top=1; st[top]=x; for (int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; while (top) pushdown(st[top--]); while (!isroot(x)) { int y=fa[x],z=fa[y]; if (!isroot(y)) { if (c[y][0]==x^c[z][0]==y) rotate(x);else rotate(y); } rotate(x); } } void access(int x) { int t=0; while (x) { splay(x); c[x][1]=t; update(x); t=x; x=fa[x]; } } void makeroot(int x) { access(x);splay(x);rev[x]^=1; } int find(int x) { access(x);splay(x); while (c[x][0]) x=c[x][0]; return x; } void link(int x,int y) { makeroot(x); fa[x]=y; } int main() { n=read(); for (int i=1;i<=n;i++) v[i]=sum[i]=read(); q=read(); while (q--) { char ch[20]; scanf("%s",ch); int x=read(),y=read(); if (ch[0]=='b') { if (find(x)!=find(y)) { puts("yes"); link(x,y); } else puts("no"); } else if (ch[0]=='p') { makeroot(x); v[x]=y; update(x); } else { if (find(x)==find(y)) { makeroot(x); access(y); splay(y); printf("%d\n",sum[y]); } else puts("impossible"); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-72324.html

最新回复(0)