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\n", 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\n",  query1(1, n, 1, l, r, k) + 1);
        } 
        if(opt == 2)
        {
            scanf("%d%d%d", &l, &r, &k);
            printf("%d\n", 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\n", query3(1, n, 1, l, r, k));
        }
        if(opt == 5)
        {
            scanf("%d%d%d", &l, &r, &k);
            printf("%d\n", query4(1, n, 1, l, r, k));
        }
    }
//    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

 

posted @ 2017-05-30 21:54  19992147  阅读(173)  评论(0编辑  收藏  举报