bzoj3110: [Zjoi2013]K大数查询

来源:互联网 发布:社交软件架构 编辑:程序博客网 时间:2024/05/22 12:30

传送门
外层权值线段树套内层普通线段树水过。

#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<cstring>#include<algorithm> #define N 20000005#define u32 unsigned intusing namespace std;u32 n,m,tot,a,b,c,d,rt[400005],ls[N],rs[N],sum[N],tag[N];void pushdown(u32 k,u32 l,u32 r){    if (l==r||!tag[k]) return;    if (!ls[k]) ls[k]=++tot;    if (!rs[k]) rs[k]=++tot;    tag[ls[k]]+=tag[k],tag[rs[k]]+=tag[k];    u32 mid=(l+r)/2;    sum[ls[k]]+=(mid-l+1)*tag[k];    sum[rs[k]]+=(r-mid)*tag[k];    tag[k]=0;}void add(u32 &k,u32 l,u32 r,u32 a,u32 b){    if (!k) k=++tot;    pushdown(k,l,r);    if (l==a&&r==b){        sum[k]+=r-l+1;        tag[k]++;        return;    }    u32 mid=(l+r)/2;    if (b<=mid) add(ls[k],l,mid,a,b);    else if (a>mid) add(rs[k],mid+1,r,a,b);    else add(ls[k],l,mid,a,mid),add(rs[k],mid+1,r,mid+1,b);    sum[k]=sum[ls[k]]+sum[rs[k]]; }void addd(u32 a,u32 b,u32 c){    u32 l=1,r=n*2+1,k=1,mid;    while (l!=r){        mid=(l+r)/2;        add(rt[k],1,n,a,b);        if (c<=mid) r=mid,k*=2;        else l=mid+1,k=k*2+1;    }    add(rt[k],1,n,a,b);}u32 ask(u32 k,u32 l,u32 r,u32 a,u32 b){    if (!k) return 0;    pushdown(k,l,r);    if (l==a&&r==b) return sum[k];    u32 mid=(l+r)/2;    if (b<=mid) return ask(ls[k],l,mid,a,b);    if (a>mid) return ask(rs[k],mid+1,r,a,b);    return ask(ls[k],l,mid,a,mid)+ask(rs[k],mid+1,r,mid+1,b);} u32 solve(u32 a,u32 b,u32 c){    u32 k=1,l=1,r=n*2+1,mid,t;    for (;l!=r;){        mid=(l+r)/2;        t=ask(rt[k*2],1,n,a,b);        if (c<=t) r=mid,k*=2;        else l=mid+1,k=k*2+1,c-=t;    }    return l;}int main(){    scanf("%u%u",&n,&m);    for (u32 i=1;i<=m;i++){        scanf("%u%u%u%u",&a,&b,&c,&d);        if (a==1) addd(b,c,n-d+1);        else printf("%u\n",n-solve(b,c,d)+1);    }}
0 0