zoukankan      html  css  js  c++  java
  • [HNOI2010] 弹飞绵羊

    传送门:>Here<

    题意:有N个弹力装置,第i个弹力装置能够把绵羊从i弹到i+k[i],如果i+k[i]仍然在N之内则接着弹,如果超出N则绵羊被弹飞。现有两种询问:1. 输出从i位置弹几次被弹飞 2.把弹力装置i的k[i]修改为y

    解题思路

    考虑用LCT来维护弹力装置之间的关系。如果第$i$个弹力装置的弹力系数为$k[i]$,则$link(i, i+k[i])$。如果$i+k[i] > N$,则需要增加虚拟节点$N+1$,可以形象的用来表示被弹飞

    因此从$i$出发几次被弹飞也就可以转化为节点$i$到$N+1$之间路径的长度。要求路径长度只需要动态维护链的长度即可——即$split(x, N+1)$,并且用splay维护size。

    对于修改弹力系数,也就等于修改了LCT的构建方式。此时我们需要断开旧边,重新连接新边。先$cut$再$link$即可

    Code

      编号是从0开始的(调了1小时),pushup的时候不要把size[ch[x][0]]打成了ch[x][0](调了40多分钟)

    /*By DennyQi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 200010;
    const int MAXM = 27010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * w;
    }
    int N,M,opt,x,y;
    int K[MAXN];
    struct LinkCutTree{
        int size[MAXN],ch[MAXN][2],fa[MAXN],tag[MAXN];
        inline bool rson(int f, int x){
            return ch[f][1] == x;
        }
        inline bool isroot(int x){
            return (ch[fa[x]][0] != x) && (ch[fa[x]][1] != x);
        }
        inline void pushup(int x){
            size[x] = size[ch[x][0]] + size[ch[x][1]] + 1;
        }
        inline void rotate(int x){
            int f = fa[x], gf = fa[f];
            int p = rson(f, x), q = !p;
            if(!isroot(f)) ch[gf][rson(gf,f)] = x;
            fa[x] = gf;
            ch[f][p] = ch[x][q], fa[ch[x][q]] = f;
            ch[x][q] = f, fa[f] = x;
            pushup(f), pushup(x);
        }
        void pushdown(int x){
            if(!isroot(x)) pushdown(fa[x]);
            if(!tag[x]) return;
            swap(ch[x][0], ch[x][1]);
            tag[ch[x][0]] ^= 1;
            tag[ch[x][1]] ^= 1;
            tag[x] = 0;
        }
        inline void splay(int x){
            pushdown(x);
            while(!isroot(x)){
                int f = fa[x], gf = fa[f];
                if(isroot(f)){
                    rotate(x);
                    break;
                }
                if(rson(gf,f) != rson(f,x)){
                    rotate(x), rotate(x);
                }
                else{
                    rotate(f), rotate(x);
                }
            }
        }
        inline void access(int x){
            for(int y = 0; x; y = x, x = fa[x]){
                splay(x);
                ch[x][1] = y;
                pushup(x);
            }
        }
        inline void makeroot(int x){
            access(x);
            splay(x);
            tag[x] ^= 1;
        }
        inline int findroot(int x){
            access(x);
            splay(x);
            for(; ch[x][0]; x = ch[x][0]);
            return x;
        }
        inline void split(int x, int y){
            makeroot(x);
            access(y);
            splay(y);
        }
        inline void link(int x, int y){
            makeroot(x);
            fa[x] = y;
        }
        inline void cut(int x, int y){
            split(x, y);
            if(ch[y][0] != x || ch[x][1] != 0) return;
            fa[x] = ch[y][0] = 0;
        }
        inline int query(int x){
            split(x, N+1);
            return size[N+1] - 1;
        }
    }qxz;
    int main(){
        N = r;
        for(int i = 1; i <= N; ++i){
            K[i] = r;
            if(i + K[i] > N){
                qxz.link(i, N+1);
            }
            else{
                qxz.link(i, i + K[i]);
            }
        }
        M = r;
        while(M--){
            opt = r, x = r + 1;
            if(opt == 1){
                printf("%d
    ", qxz.query(x));
            }
            else{
                y = r;
                if(x + K[x] > N){
                    qxz.cut(x, N+1);
                }
                else{
                    qxz.cut(x, x+K[x]);
                }
                if(x + y > N){
                    qxz.link(x, N+1);
                }
                else{
                    qxz.link(x, x+y);
                }
                K[x] = y;
            }
        }
        return 0;
    }
  • 相关阅读:
    IDEA 工具 破解码
    postman 使用 及断言
    MonkeyTest 命名
    Jmeter 测试单元的封装与复用
    开发性能测试工具——自己动手实现迭代功能
    jemter安装mysql数据驱动JDBC
    全链路性能测试知识点整理
    Java接口全链路优化:如何降低接口RT时长(转)
    测试自动化之Mock服务思路探讨
    算法分析与设计(一)时间与空间复杂度
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9446693.html
Copyright © 2011-2022 走看看