【BZOJ-2843&1180】极地旅行社&OTOCI Link-Cut-Tree
2843: 极地旅行社
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 323 Solved: 218
[Submit][Status][Discuss]
Description
Input
第一行一个正整数N,表示冰岛的数量。
第二行N个范围[0, 1000]的整数,为每座岛屿初始的帝企鹅数量。
第三行一个正整数M,表示命令的数量。
接下来M行即命令,为题目描述所示。
Output
对于每个bridge命令与excursion命令,输出一行,为题目描述所示。
Sample Input
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
impossible
yes
6
yes
yes
15
yes
15
16
HINT
1<=N<=30000 |
1<=M<=100000 |
Source
1180: [CROATIAN2009]OTOCI
Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 795 Solved: 493
[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
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
impossible
yes
6
yes
yes
15
yes
15
16
HINT
Source
Solution
很简单的LCT,支持三种操作,合并,查询区间和,单点修改
合并操作没什么可说的,可以开个并查集维护一下联通性,当然直接用LCT里的find函数也可以
查询区间和,同样,维护一个sum即可
单点修改很简单,修改val后access,splay一下更新一下值即可
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; 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; } #define N 50000 #define M 100010 int fa[N],son[N][2],s[N],val[N],size[N],sum[N]; bool rev[N];int father[N];int n,m; inline void init(){for (int i=1; i<=n; i++) father[i]=i;} inline int find(int x){if (x==father[x]) return x; return father[x]=find(father[x]);} inline void merge(int x,int y) {int fx=find(x),fy=find(y); if (fx!=fy) father[fx]=fy;} //bing cha ji inline bool is_root(int x){return !fa[x]||son[fa[x]][1]!=x&& son[fa[x]][0]!=x;} inline void rev1(int x){if (!x)return; swap(son[x][0],son[x][1]);rev[x]^=1;} void pb(int x){if (rev[x]) rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;} inline void update(int x) { sum[x]=val[x]; if (son[x][0]) sum[x]+=sum[son[x][0]]; if (son[x][1]) sum[x]+=sum[son[x][1]]; size[x]=size[son[x][0]]+1+size[son[x][1]]; } inline void rotate(int x) { int y=fa[x],w=son[y][1]==x;son[y][w]=son[x][w^1]; if (son[x][w^1]) fa[son[x][w^1]]=y; if (fa[y]) { int z=fa[y];if (son[z][0]==y) son[z][0]=x; else if (son[z][1]==y) son[z][1]=x; } fa[x]=fa[y]; fa[y]=x; son[x][w^1]=y; update(y); } inline void splay(int x) { int top=1,i=x,y; s[1]=i; while (!is_root(i)) s[++top]=i=fa[i]; while (top) pb(s[top--]); while (!is_root(x)) { y=fa[x]; if (!is_root(y)) if ((son[fa[y]][0]==y)^(son[y][0]==x)) rotate(x);else rotate(y); rotate(x); } update(x); } inline void access(int x){for (int y=0; x; y=x,x=fa[x])splay(x),son[x][1]=y,update(x);} inline void makeroot(int x){access(x),splay(x),rev1(x);} inline void link(int x,int y){makeroot(x); fa[x]=y; access(x);} inline void cutf(int x){access(x),splay(x);fa[son[x][0]]=0; son[x][0]=0; update(x);} inline void cut(int x,int y){makeroot(x); cutf(y);} inline void split(int x,int y){makeroot(x);access(y);splay(y);} inline int ask(int x,int y){split(x,y);return sum[y];} //Link Cut Tree void excursion(int x,int y) { int f1=find(x),f2=find(y); if (f1!=f2) {puts("impossible");return;} printf("%d\n",ask(x,y)); } void bridge(int x,int y) { int f1=find(x),f2=find(y); if (f1==f2) {puts("no");return;} link(x,y); merge(x,y); puts("yes"); } void penguins(int x,int y) { val[x]=y; access(x); splay(x); } int main() { n=read(); for (int i=1; i<=n; i++) val[i]=read(),sum[i]=val[i]; m=read(); init(); for (int i=1; i<=m; i++) { char opt[10]; scanf("%s",opt); int x=read(),y=read(); switch (opt[0]) { case 'e': excursion(x,y);break; case 'b': bridge(x,y);break; case 'p': penguins(x,y);break; } } return 0; }
一开始没仔细看,还打了个标记?...然后样例就错了最后一个询问...一看题,单点修改...改后1A...跑得比西方记者还快!