• 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
    ",query(x,y));
    89         }
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    最大子数组和问题的解
    【剑指Offer】46孩子们的游戏(圆圈中最后剩下的数)
    【剑指Offer】45扑克牌顺子
    【剑指Offer】44翻转单词顺序列
    【剑指Offer】43左旋转字符串
    【剑指Offer】42和为S的两个数字
    【剑指Offer】41和为S的连续正数序列
    【剑指Offer】40数组中只出现一次的数字
    【剑指Offer】39平衡二叉树
    【剑指Offer】38二叉树的深度
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8150398.html
Copyright © 2020-2023  润新知