POJ 2104:K-th Number 整体二分

感觉整体二分是个很有趣的东西。

在别人的博客上看到一句话

对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了

 

树套树写了一天还是WA着,调得焦头烂额,所以决定学cdq分治的写法,虽然不知道整体二分和cdq有什么不可不说的关系,就先写了这道主席树模板题(orz LLZ大佬)。

然后历史总是惊人的相似,和上午写cdq分治一样,又在同一个地方栽了跟头

两个cdq模板都是cmp写错,两个整体二分都是把que[i]写成了i QAQ

然后这个代码在洛谷上会T掉,在POJ可以A,就很难受了(vjudge上waiting了35分钟。。。)

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100000+100000+299;
const int INF=1e9+7;
int n,m,tot,sum[maxn],ans[maxn]; 
struct node{
    int op,id,l,r,v;
    node(){};
    node(int op,int id,int l,int r,int v):op(op),id(id),l(l),r(r),v(v){}
}p[maxn],tp[maxn];
void input() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        int x;
        scanf("%d",&x);
        p[i]=node(1,i,i,i,x);
    }
    for(int i=1;i<=m;i++) {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        p[i+n]=node(0,i,x,y,z);
    }
}
void add(int x,int y) {
    for(;x<=n+m;x+=(x&(-x))) 
        sum[x]+=y;
}
int qry(int x) {
    int res=0;
    for(;x;x-=(x&(-x)))
        res+=sum[x];
    return res;   
}
#define mid ((l+r)>>1)
int lq[maxn],rq[maxn];
void solve(int ql,int qr,int l,int r) {
    if(l==5&&r==6) {
       int debug=1;
    }
    //int mid=((l+r)>>1);
    if(r<l||qr<ql) return;
    if(l==r) {
        for(int i=ql;i<=qr;i++) 
            if(p[i].op==0)
                ans[p[i].id]=l;
        return;
    }
    int lcnt=0,rcnt=0;
    for(int i=ql;i<=qr;i++) {
        if(p[i].op) {   //insert
            if(p[i].v<=mid) {
                add(p[i].id,1);
                lq[++lcnt]=i;
            }
            else rq[++rcnt]=i;
        }
        else {  //query
            int now=qry(p[i].r)-qry(p[i].l-1);
            if(now>=p[i].v) lq[++lcnt]=i;
            else p[i].v-=now,rq[++rcnt]=i; 
        }
    }
    for(int i=1;i<=lcnt;i++) 
        if(p[lq[i]].op&&p[lq[i]].v<=mid) add(p[lq[i]].id,-1); 
    for(int i=0;i<lcnt;i++) tp[ql+i]=p[lq[i+1]];
    for(int i=0;i<rcnt;i++) tp[ql+lcnt+i]=p[rq[i+1]];
    for(int i=ql;i<=qr;i++) p[i]=tp[i];
    solve(ql,ql+lcnt-1,l,mid); 
    solve(ql+lcnt,qr,mid+1,r);
}
void print() {
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
}
int main()
{
    input();
    solve(1,m+n,-INF,INF);
    print();
    return 0;
}
K-th number

 

posted @ 2017-09-05 15:22  啊宸  阅读(200)  评论(0编辑  收藏  举报