BZOJ 1901 Zju 2112 Dynamic Rankings 动态维护第k小 树套树

题目大意:动态维护第k小。

思路:线段树套treap,裸题,就是不怎么好写。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 50010
#define INF 1e9
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
#define SIZE(x) ((x == NULL) ? 0:x->size)
using namespace std;

struct Complex{
    int val,cnt,size,random;
    Complex *son[2];

    Complex() {
        son[0] = son[1] = NULL;
        cnt = size = 1;
        random = rand();
    }
    int Compare(int x) {
        if(x == val)    return -1;
        return x > val;
    }
    void Maintain() {
        size = cnt;
        if(son[0] != NULL)  size += son[0]->size;
        if(son[1] != NULL)  size += son[1]->size;
    }
};

int cnt,asks;
int src[MAX];

char s[10];

Complex *tree[MAX << 2];

void Pretreatment();

void BuildTree(int l,int r,int pos);
int GetRank(int l,int r,int x,int y,int pos,int k);
int GetKth(int x,int y,int k);
void Modify(int l,int r,int aim,int pos,int c);

inline void Rotate(Complex *&a,bool dir);
void Insert(Complex *&a,int x);
void Delete(Complex *&a,int x);
int GetRank(Complex *a,int k);

int main()
{
    Pretreatment();
    cin >> cnt >> asks;
    for(int i = 1;i <= cnt; ++i)
        scanf("%d",&src[i]);
    BuildTree(1,cnt,1);
    for(int i = 1;i <= asks; ++i) {
        scanf("%s",s);
        int x,y,z;
        if(s[0] == 'Q') {
            scanf("%d%d%d",&x,&y,&z);
            printf("%d\n",GetKth(x,y,z));
        }
        if(s[0] == 'C') {
            scanf("%d%d",&x,&y);
            Modify(1,cnt,x,1,y);
            src[x] = y;
        }
    }
    return 0;
}

void Pretreatment()
{
    memset(tree,NULL,sizeof(tree));
}

void BuildTree(int l,int r,int pos)
{
    for(int i = l;i <= r; ++i)
        Insert(tree[pos],src[i]);
    if(l == r)  return ;
    int mid = (l + r) >> 1;
    BuildTree(l,mid,LEFT);
    BuildTree(mid + 1,r,RIGHT);
}

int GetRank(int l,int r,int x,int y,int pos,int k)
{
    if(l == x && y == r)
        return GetRank(tree[pos],k);
    int mid = (l + r) >> 1;
    if(y <= mid) return GetRank(l,mid,x,y,LEFT,k);
    if(x > mid)      return GetRank(mid + 1,r,x,y,RIGHT,k);
    int left = GetRank(l,mid,x,mid,LEFT,k);
    int right = GetRank(mid + 1,r,mid + 1,y,RIGHT,k);
    return left + right;
}

int GetKth(int x,int y,int k)
{
    int L = 0,R = INF;
    while(L <= R) {
        int mid = (L + R) >> 1;
        int temp = GetRank(1,cnt,x,y,1,mid);
        if(temp < k) L = mid + 1;
        else    R = mid - 1;
    }
    return L;
}

void Modify(int l,int r,int aim,int pos,int c)
{
    Delete(tree[pos],src[aim]);
    Insert(tree[pos],c);
    if(l == r)  return ;
    int mid = (l + r) >> 1;
    if(aim <= mid)   Modify(l,mid,aim,LEFT,c);
    else    Modify(mid + 1,r,aim,RIGHT,c);
}

inline void Rotate(Complex *&a,bool dir)
{
    Complex *k = a->son[!dir];
    a->son[!dir] = k->son[dir];
    k->son[dir] = a;
    a->Maintain(),k->Maintain();
    a = k;
}

void Insert(Complex *&a,int x)
{
    if(a == NULL) {
        a = new Complex();
        a->val = x;
        return ;
    }
    int dir = a->Compare(x);
    if(dir == -1)
        a->cnt++;
    else {
        Insert(a->son[dir],x);
        if(a->son[dir]->random > a->random)
            Rotate(a,!dir);
    }
    a->Maintain();
}

void Delete(Complex *&a,int x)
{
    int dir = a->Compare(x);
    if(dir != -1)
        Delete(a->son[dir],x);
    else {
        if(a->cnt > 1)    a->cnt--;
        else {
            if(a->son[0] == NULL)    a = a->son[1];
            else if(a->son[1] == NULL)   a = a->son[0];
            else {
                bool _dir = (a->son[0]->random > a->son[1]->random);
                Rotate(a,_dir);
                Delete(a->son[_dir],x);
            }
        }
    }
    if(a != NULL)   a->Maintain();
}

int GetRank(Complex *a,int k)
{
    if(a == NULL)   return 0;
    if(k < a->val)   return GetRank(a->son[0],k);
    int p = SIZE(a->son[0]) + a->cnt;
    if(k > a->val)  p += GetRank(a->son[1],k);
    return p;
}
时间: 2025-01-02 15:33:26

BZOJ 1901 Zju 2112 Dynamic Rankings 动态维护第k小 树套树的相关文章

BZOJ 1901 Zju 2112 Dynamic Rankings 带修改主席树

题目大意:给出一个序列,单点修改,询问区间第k大. 思路:如果不带修改,那么划分树就可以解决,但是划分树是静态的树,不支持修改.带修改的主席舒其实就是外层fenwick套内层权值线段树,但是权值线段树必须动态开节点.然后修改的时候就像树状数组修改那样,每次修改logn个权值线段树.查询的时候也一样,返回logn个权值线段树统计的和. 最后为了求区间第k大,还需要二分答案. CODE: #include <cstdio> #include <cstring> #include <

zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 Description The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query l

ZJU 2112 Dynamic Rankings

Dynamic Rankings Time Limit: 10000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original ID: 211264-bit integer IO format: %lld      Java class name: Main The Company Dynamic Rankings has developed a new kind of computer that is no lon

zoj2112 Dynamic Rankings 动态区间第k大,树状数组套平衡树

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int

【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题

达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状数组,而我一开始根本不知道该怎么套,, 学习吧,,, 然后我自己脑补如果不套会如何?后来想到是查询O(logn),修改是O(nlogn),很明显修改的复杂度太大了,为了降低修改的复杂度,我们只得套上树状数组来维护前缀和使它的n的复杂度降低为logn,从而修改的复杂度变为O(log2n).但因为我们套

ZOJ 2112 Dynamic Rankings(主席树の动态kth)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. T

bzoj 1901: Zju2112 Dynamic Rankings(树套树)

1901: Zju2112 Dynamic Rankings 经典的带修改求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,而且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过不了. 思路很简单,用线段树维护区间,用splay维护区间内的权值,然后询问的时候,二分答案key,然后在区间内找小于key的数有多少个. 贴上模板: #include<stdio.h> #include<string.h> #include<algorithm> #def

zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

zoj 2112 Dynamic Rankings 带修改区间第K大 动态主席树

pass 首先,个人觉得把这个数据结构理解成树状数组套主席树是十分不严谨的.主席树的本质是可持久化权值线段树与前缀和思想的结合.而动态主席树是可持久化权值线段树与树状数组思想的结合.并非树套树般的泾渭分明的叠加. 其次,大概讲下对动态主席树的理解.我们静态主席树中,第i个版本维护的是[1,i]的权值线段树,我们利用前缀和的思想,通过y的版本-x的版本得到[x,y]的权值线段树,从而剥离出一颗对应区间的权值线段树.我们考虑在这个情况下,如果需要修改第a[i]的值,那么从i,i+1,i+2.....