zoukankan      html  css  js  c++  java
  • bzoj3196

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196

    树套树!

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 3000010, inf = 1000000000;
    int n, m, cnt;
    int a[N];
    namespace splaytree
    {
        int child[N][2], size[N], fa[N], key[N], root[N], num[N];
        void update(int x)
        {
            size[x] = num[x] + size[child[x][0]] + size[child[x][1]];
        }
        void zig(int x)
        {
            int y = fa[x]; 
            fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x;
            child[y][0] = child[x][1]; fa[child[x][1]] = y;
            fa[y] = x; child[x][1] = y;
            update(y); update(x);
        }
        void zag(int x)
        {
            int y = fa[x]; 
            fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x;
            child[y][1] = child[x][0]; fa[child[x][0]] = y;
            fa[y] = x; child[x][0] = y;
            update(y); update(x);
        }
        void splay(int x, int t, int pos)
        {
            while(fa[x] != t)
            {
                int y = fa[x], z = fa[y];
                if(z == t) 
                {
                    child[y][0] == x ? zig(x) : zag(x); break;
                }
                else if(y == child[z][0] && x == child[y][0]) { zig(y); zig(x); }
                else if(y == child[z][1] && x == child[y][1]) { zag(y); zag(x); }
                else if(y == child[z][0] && x == child[y][1]) { zag(x); zig(x); }
                else if(y == child[z][1] && x == child[y][0]) { zig(x); zag(x); }
            }
            if(!t) root[pos] = x;
            update(root[pos]);
        }
        int getrnk(int x, int k)
        {
            int ret = 0;
            while(x)
            {
                if(k == key[x]) 
                {
                    ret += (child[x][0] ? size[child[x][0]] : 0);
                    break;            
                }
                if(k > key[x]) 
                {
                    ret += num[x] + size[child[x][0]];
                    x = child[x][1];
                }
                else x = child[x][0];
            }
            return ret;
        }
        void up(int x)
        {
            while(x) 
            {
                update(x); 
                x = fa[x];
            }
        }
        int find(int x, int k)
        {
            for(int now = x; now; now = child[now][k > key[now]])
                if(key[now] == k) return now;
        }
        void del(int x, int k)
        {
            splay(k, 0, x);
            if(num[k] > 1)
            {
                --num[k];
                up(k);
                return;
            }
            if(child[k][0] * child[k][1] == 0)
            {
                root[x] = child[k][0] + child[k][1];
                fa[root[x]] = 0; 
                fa[k] = child[k][0] = child[k][1] = num[k] = size[k] = key[k] = 0;
                update(root[x]);
                return;
            }
            int now = child[k][1];
            while(child[now][0]) now = child[now][0];
            fa[child[k][0]] = now; child[now][0] = child[k][0];
            root[x] = child[k][1]; fa[root[x]] = 0;
            up(child[k][0]);
            fa[k] = child[k][0] = child[k][1] = size[k] = num[k] = 0;
            splay(now, 0, x);
        }
        void insert(int x, int k)
        {
            if(!root[x]) 
            {
                root[x] = ++cnt;
                num[cnt] = size[cnt] = 1;
                key[cnt] = k;
                return;
            }
            int now = root[x];
            while(1)
            {
                if(key[now] == k) 
                {
                    ++num[now];
                    up(now);
                    return;
                }
                if(!child[now][k > key[now]])
                {
                    child[now][k > key[now]] = ++cnt;
                    num[cnt] = size[cnt] = 1;
                    fa[cnt] = now;
                    key[cnt] = k;
                    up(cnt);
                    return;
                }
                now = child[now][k > key[now]];
            } 
        }
        int Pre(int x, int k)
        {
            int now = root[x], ret = 0;
            while(now)
            {
                if(key[now] < k) ret = max(ret, key[now]);
                if(key[now] < k) now = child[now][1];
                else now = child[now][0];
            }
            return ret;
        }
        int Nxt(int x, int k)
        {
            int now = root[x], ret = inf;
            while(now)
            {
                if(key[now] > k) ret = min(ret, key[now]);
                if(key[now] > k) now = child[now][0];
                else now = child[now][1]; 
            }
            return ret;
        }
    } using namespace splaytree;
    namespace segmenttree
    {
        void build(int l, int r, int x)
        {
            if(l == r) 
            {
                root[x] = ++cnt;
                size[cnt] = num[cnt] = 1;
                key[cnt] = a[l];
                return;
            }
            int mid = (l + r) >> 1;
            build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1);
            for(int i = l; i <= r; ++i) insert(x, a[i]);     
        } 
        int query1(int l, int r, int x, int a, int b, int k)
        { //一个数在区间内的排名 
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return getrnk(root[x], k);
            int mid = (l + r) >> 1;
            return (query1(l, mid, x << 1, a, b, k) + query1(mid + 1, r, x << 1 | 1, a, b, k));
        }
        int querynum(int l, int r, int k)
        {
            int L = 0, R = 100000010, mid, ans = -1;
            while(R - L > 1)
            {
                mid = (L + R) >> 1;
                int t = query1(1, n, 1, l, r, mid);
                if(t < k) L = mid;
                else R = mid;  
            }
            return L;
        }
        void modify(int l, int r, int x, int pos, int k)
        {
            if(l == r)
            {
                root[x] = ++cnt;
                key[cnt] = k;
                num[cnt] = size[cnt] = 1;
                return;
            }
            int mid = (l + r) >> 1;
            if(pos <= mid) modify(l, mid, x << 1, pos, k);
            else modify(mid + 1, r, x << 1 | 1, pos, k);
            int t = find(root[x], a[pos]);    
            del(x, t); insert(x, k);
        }
        int query3(int l, int r, int x, int a, int b, int k)
        { //找前继 
            if(l > b || r < a) return -inf;
            if(l >= a && r <= b) return Pre(x, k);
            int mid = (l + r) >> 1;
            return max(query3(l, mid, x << 1, a, b, k), query3(mid + 1, r, x << 1 | 1, a, b, k));
        }
        int query4(int l, int r, int x, int a, int b, int k)
        {
    //        printf("l=%d r=%d
    ", l, r);
            if(l > b || r < a) return inf;
            if(l >= a && r <= b) return Nxt(x, k);
            int mid = (l + r) >> 1;
            return min(query4(l, mid, x << 1, a, b, k), query4(mid + 1, r, x << 1 | 1, a, b, k));
        }
    } using namespace segmenttree;
    int main()
    {
    //    freopen("psh.in", "r", stdin);
    //    freopen("psh.out", "w", stdout);
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        build(1, n, 1);
        while(m--)
        {
            int opt, l, r, k, pos, t = 0;
            scanf("%d", &opt);
            if(opt == 1)
            {
                scanf("%d%d%d", &l, &r, &k);
                printf("%d
    ",  query1(1, n, 1, l, r, k) + 1);
            } 
            if(opt == 2)
            {
                scanf("%d%d%d", &l, &r, &k);
                printf("%d
    ", querynum(l, r, k));
            }
            if(opt == 3)
            {
                scanf("%d%d", &pos, &k);
                modify(1, n, 1, pos, k);
                a[pos] = k;
            }
            if(opt == 4)
            {
                scanf("%d%d%d", &l, &r, &k);
                printf("%d
    ", query3(1, n, 1, l, r, k));
            }
            if(opt == 5)
            {
                scanf("%d%d%d", &l, &r, &k);
                printf("%d
    ", query4(1, n, 1, l, r, k));
            }
        }
    //    fclose(stdin); fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    js 判断图片是否加载完成
    js检测密码强度
    javascript 的MD5代码备份,跟java互通
    JavaScript实现限时抢购实例
    JS日期比较大小 给定时间和持续时间计算最终时间
    jquery与json的结合
    div内容过长自动省略号
    高并发大流量专题---11、Web服务器的负载均衡
    如何利用nginx实现负载均衡(总结)
    高并发大流量专题---10、MySQL数据库层的优化
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6921599.html
Copyright © 2011-2022 走看看