加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

[BZOJ3110][Zjoi2013]K大数查询

发布时间:2020-12-14 02:04:30 所属栏目:大数据 来源:网络整理
导读:[Zjoi2013]K大数查询 Description 有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。 Input 第一行N,M 接下来M行,每

[Zjoi2013]K大数查询

Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。?
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中abs(c)<=Maxlongint

Solution
本来想树状数组套权值线段树的,发现空间炸裂,无奈只能权值套区间线段树。
外层是权值线段树,维护的是权值在[l,r]之间的数出现在了哪些区间,这个哪些区间就用挂在它下面的区间线段树来维护。
然后我们二分就可以做了。

Code

#include <bits/stdc++.h>
using namespace std;

#define rep(i,l,r) for (int i = (l); i <= (r); i++)
#define per(i,r,l) for (int i = (r); i >= (l); i--)
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define MS(_) memset(_,sizeof(_))
#define debug(...) fprintf(stderr,__VA_ARGS__)

typedef unsigned int ll;

const int N = 50000 + 10;
struct node{
    ll sum,tag;
    node *lc,*rc;
    void modify(int l,int r,ll d) {sum += 1ll * (r-l+1) * d; tag += d;}
    void sink(int l,int r);
    void update() {sum = (lc ? lc->sum : 0) + (rc ? rc->sum : 0);}
}pool[N * 600],*tail = pool;
inline node *newnode() {return tail++;}
inline void node::sink(int l,int r){
    if (!lc) lc = newnode(); lc->modify(l,l+r>>1,tag);
    if (!rc) rc = newnode(); rc->modify((l+r>>1)+1,tag);
    tag = 0;
}

struct NODE{ 
    node *root;
    NODE *LC,*RC;
}POOL[N << 2],*ROOT,*TAIL = POOL;
inline NODE *NEWNODE() {return TAIL++;}

int n,m;

template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}

inline void BUILD(NODE *(&RT),int L,int R){
    RT = NEWNODE();  RT->root = newnode();
    if (L == R) return;
    int MID = L+R >> 1;
    BUILD(RT->LC,L,MID); BUILD(RT->RC,MID+1,R);
}
inline void insert(node *rt,int l,int ql,int qr){
    rt->sink(l,r);
    if (ql <= l && r <= qr) rt->modify(l,1);
    else{
        int mid = l+r >> 1;
        if (ql <= mid){
            if (!rt->lc) rt->lc = newnode(); insert(rt->lc,mid,ql,qr);
        }
        if (qr > mid){
            if (!rt->rc) rt->rc = newnode(); insert(rt->rc,mid+1,qr);
        }
        rt->update();
    }
}
inline void INSERT(NODE *RT,int R,int qr,int pos){
    insert(RT->root,1,n,qr);
    if (L == R) return;
    int MID = L+R >> 1;
    if (pos <= MID) INSERT(RT->LC,MID,qr,pos);
    else INSERT(RT->RC,R,pos);
}
inline ll query(node *rt,r);
    if (ql <= l && r <= qr) return rt->sum;
    int mid = l+r >> 1; ll res = 0;
    if (ql <= mid && rt->lc) res += query(rt->lc,qr);
    if (qr > mid && rt->rc) res += query(rt->rc,qr);
    return res;
}
inline void QUERY(NODE *RT,int rank){
    if (L == R) {printf("%dn",L); return;}
    ll cnt = query(RT->RC->root,qr);
    //debug("X = %d,ql = %d,qr = %d,cnt = %dn",(L+R) >> 1,cnt);
    int MID = L+R >> 1;
    if (cnt < rank) QUERY(RT->LC,rank-cnt);
    else QUERY(RT->RC,rank);
}

int main(){
    read(n); read(m);
    BUILD(ROOT,n);
    rep(i,m){ int op,a,b,c;
        read(op); read(a); read(b); read(c);
        if (op == 1) INSERT(ROOT,c);
        else QUERY(ROOT,c);
    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读