感觉整体二分是个很有趣的东西。
在别人的博客上看到一句话
对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了
树套树写了一天还是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
",ans[i]);
}
int main()
{
input();
solve(1,m+n,-INF,INF);
print();
return 0;
}