zoukankan      html  css  js  c++  java
  • 【BZOJ-2843&1180】极地旅行社&OTOCI Link-Cut-Tree

    2843: 极地旅行社

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 323  Solved: 218
    [Submit][Status][Discuss]

    Description

    不久之前,Mirko建立了一个旅行社,名叫“极地之梦”。这家旅行社在北极附近购买了N座冰岛,并且提供观光服务。当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间。
    Mirko的旅行社遭受一次重大打击,以至于观光游轮已经不划算了。旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客。Mirko希望开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生。
    这些冰岛从1到N标号。一开始时这些岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的。每座岛上的企鹅数量虽然会有所改变,但是始终在[0, 1000]之间。
    你的程序需要处理以下三种命令:
    1."bridge A B"——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当A与B不联通。若这项命令被接受,你的程序需要输出"yes",之后会建造这座大桥。否则,你的程序需要输出"no"。
    2."penguins A X"——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不需要回应。
    3."excursion A B"——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出"impossible"。

    Input

    第一行一个正整数N,表示冰岛的数量。

    第二行N个范围[0, 1000]的整数,为每座岛屿初始的帝企鹅数量。

    第三行一个正整数M,表示命令的数量。

    接下来M行即命令,为题目描述所示。

    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

    HINT


    1<=N<=30000


    1<=M<=100000

    Source

    1180: [CROATIAN2009]OTOCI

    Time Limit: 50 Sec  Memory Limit: 162 MB
    Submit: 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

    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

    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
    ",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...跑得比西方记者还快!

  • 相关阅读:
    推荐6款优秀的海外免费杀毒软件 附下载链接
    30个高质量的Psd设计文件分享
    45个设计师们不常见的html5和css3漂亮模板
    40个极简WordPress主题
    makfile中 override 与 +=联合作用的验证
    对 makefile 中 flavor 函数的学习体会
    GNU make manual 翻译( 一百六十七)
    对 makefile 中 override 优先级的学习体会
    GNU make manual 翻译( 一百六十五)
    GNU make manual 翻译( 一百六十六)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5343961.html
Copyright © 2011-2022 走看看