整体二分,区间第K小(CRB and Queries,HDU 5412)

来源:互联网 发布:淘宝筛选发货地怎么改 编辑:程序博客网 时间:2024/06/11 00:37

题目链接:https://vjudge.net/problem/HDU-5412


静态区间第K小,可以使用主席树或整体二分。

动态区间第K小,可以使用树套树或整体二分。


参考博客:http://blog.csdn.net/v5zsq/article/details/50775827


代码

#include<stdio.h>using namespace std;const int maxn = 100010;const int inf = 1e9+7;int N;int A[maxn];int Q;struct op{    int tp,a,b,k;    int r,cur;}o[maxn<<2],o1[maxn<<2],o2[maxn<<2];int num,cnt;int ans[maxn];int temp[maxn<<2];////////////////////////////树状数组int BIT[maxn];int low_bit(int x){    return x&-x;}void add(int p,int v){    while(p<=N)    {        BIT[p]+=v;        p+=low_bit(p);    }}int qry(int p){    int ret=0;    while(p)    {        ret+=BIT[p];        p-=low_bit(p);    }    return ret;}////////////////////////////树状数组void init_and_read(){    num=0;    cnt=0;    for(int i=1;i<=N;i++)    {        BIT[i]=0;        scanf("%d",A+i);        num++;        o[num].tp=1;        o[num].a=i;        o[num].b=A[i];    }    scanf("%d",&Q);    while(Q--)    {        int tp;        scanf("%d",&tp);        if(tp==1)        {            int i;            scanf("%d",&i);            num++;            o[num].tp=2;            o[num].a=i;            o[num].b=A[i];            num++;            o[num].tp=1;            o[num].a=i;            scanf("%d",&A[i]);            o[num].b=A[i];        }        else        {            num++;            o[num].tp=3;            scanf("%d %d %d",&o[num].a,&o[num].b,&o[num].k);            cnt++;            o[num].r=cnt;            o[num].cur=0;        }    }}void handle(int opl,int opr,int nml,int nmr){    if(opl>opr) return;    if(nml==nmr)    {        for(int i=opl;i<=opr;i++)            if(o[i].tp==3)                ans[o[i].r]=nml;        return;    }    int mid = nml+((nmr-nml)>>1);    for(int i=opl;i<=opr;i++)    {        if(o[i].tp==1&&o[i].b<=mid) add(o[i].a,1);        if(o[i].tp==2&&o[i].b<=mid) add(o[i].a,-1);        if(o[i].tp==3) temp[i]=qry(o[i].b)-qry(o[i].a-1);    }    for(int i=opl;i<=opr;i++)    {        if(o[i].tp==1&&o[i].b<=mid) add(o[i].a,-1);        if(o[i].tp==2&&o[i].b<=mid) add(o[i].a,1);    }    int numl=0,numr=0;    for(int i=opl;i<=opr;i++)    {        if(o[i].tp<=2)        {            if(o[i].b<=mid) o1[++numl]=o[i];            else o2[++numr]=o[i];        }        else        {            if(o[i].cur+temp[i]<o[i].k)            {                o[i].cur+=temp[i];                o2[++numr]=o[i];            }            else o1[++numl]=o[i];        }    }    for(int i=1;i<=numl;i++) o[opl-1+i]=o1[i];    for(int i=1;i<=numr;i++) o[opl+numl+i-1]=o2[i];    handle(opl,opl+numl-1,nml,mid);    handle(opl+numl,opr,mid+1,nmr);}void solve(){    init_and_read();    handle(1,num,0,inf);    for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]);}int main(){    while(~scanf("%d",&N)) solve();    return 0;}


阅读全文
0 0