【Luogu】P3332K大数查询(树套树)

  题目链接

  这题我费尽心思不用标记永久化终于卡过去了qwq

  权值线段树下面套一个区间线段树。然后乱搞搞即可。

  

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cctype>
#define maxn 100050
#define mid ((l+r)>>1)
#define left (root<<1)
#define right (root<<1|1)
#define check(o)    if(o==0)    o=++segtot;
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long tree[maxn*200];int segtot;
int segrt[maxn*200];
int segls[maxn*200];
int segrs[maxn*200];
int tag[maxn*200];
int rt[maxn*10];
int q[maxn];
int n,m,cnt,size;


void pushdown(int &root,int m){
    check(root);
    if(tag[root]==0)    return;
    check(segls[root]);
    check(segrs[root]);
    int le=segls[root],ri=segrs[root];
    tag[le]+=tag[root];    tag[ri]+=tag[root];
    tree[le]+=tag[root]*(m-(m>>1));
    tree[ri]+=tag[root]*(m>>1);
    tag[root]=0;
}

void segup(int from,int to,int l,int r,int &root){
    check(root);
    if(from<=l&&to>=r){
        tree[root]+=(r-l+1);
        tag[root]++;
        return;
    }
    pushdown(root,r-l+1);
    if(from<=mid){
        check(segls[root]);
        segup(from,to,l,mid,segls[root]);
    }
    if(to>mid){
        check(segrs[root]);
        segup(from,to,mid+1,r,segrs[root]);
    }
    tree[root]=tree[segls[root]]+tree[segrs[root]];
}

long long segquery(int from,int to,int l,int r,int &root){
    check(root);
    if(from<=l&&to>=r)    return tree[root];
    pushdown(root,r-l+1);
    long long ans=0;
    if(from<=mid){
        check(segls[root]);
        ans+=segquery(from,to,l,mid,segls[root]);
    }
    if(to>mid){
        check(segrs[root]);
        ans+=segquery(from,to,mid+1,r,segrs[root]);
    }
    return ans;
}

void add(int o,int from,int to,int l,int r,int p){
    segup(from,to,1,n,segrt[o]);
    if(l==r)    return;
    if(p<=mid)    add(o<<1,from,to,l,mid,p);
    else    add(o<<1|1,from,to,mid+1,r,p);
}

long long query(int o,int from,int to,long long l,long long r,long long e){
    if(l==r)    return l;
    long long ans=segquery(from,to,1,n,segrt[o<<1|1]);
    if(ans>=e)    return query(o<<1|1,from,to,mid+1,r,e);
    else        return query(o<<1,from,to,l,mid,e-ans);
}

struct Que{
    long long opt,a,b,c;
}que[maxn];

int main(){
    n=read(),m=read();
    for(int i=1;i<=m;++i){
        que[i]=(Que){read(),read(),read(),read()};
        if(que[i].opt==1)    q[++cnt]=que[i].c;
    }
    sort(q+1,q+cnt+1);
    size=unique(q+1,q+cnt+1)-q-1;
    for(int i=1;i<=m;++i){
        if(que[i].opt!=1)    continue;
        que[i].c=lower_bound(q+1,q+size+1,que[i].c)-q;
    }
    for(int i=1;i<=m;++i){
        long long  opt=que[i].opt,a=que[i].a,b=que[i].b,c=que[i].c;
        if(opt==1)    add(1,a,b,1,size,c);
        else        printf("%lld\n",q[query(1,a,b,1,size,c)]);
    }
    return 0;
}

 

posted @ 2018-01-18 19:53  Konoset  阅读(251)  评论(0编辑  收藏  举报