恩。。CDQ分治是个神奇的东西。。其思想基于分治。。可以实现大部分离线的带修改的询问

资料:http://www.cnblogs.com/zig-zag/archive/2013/04/18/3027707.html

//author: CHC
//First Edit Time: 2015-09-04 13:18
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=1e+5 + 1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
int C[MAXN],A[MAXN],n,q,ans[MAXN];
void Add(int x,int v){
for(int i=x;i<=n;i+=i&-i)C[i]+=v;
}
int Sum(int x){
int cnt=0;
for(int i=x;i>0;i-=i&-i)cnt+=C[i];
return cnt;
}
struct point {
int x,y,k,kind,qpos,delta,cur;
point(){}
point(int _x,int _y,int _k,int _kind,int _qpos,int _delta,int _cur):x(_x),y(_y),k(_k),kind(_kind),qpos(_qpos),delta(_delta),cur(_cur){}
}cs[MAXN<<2],ql[MAXN<<2],qr[MAXN<<2];
int tmp[MAXN<<2];
void cdq(int L,int R,int l,int r){
if(L>R)return ;
//printf("L:%d R:%d\n",L,R);
//printf("l:%d r:%d\n",l,r);
//system("pause");
if(l==r){
for(int i=L;i<=R;i++)
if(cs[i].kind==1)ans[cs[i].qpos]=l;
//printf("l:%d\n",l);
return;
}
int mid=(l+r)>>1;
for(int i=L;i<=R;i++){
if(cs[i].kind==0&&cs[i].y<=mid)Add(cs[i].x,cs[i].delta);
else if(cs[i].kind==1)tmp[i]=Sum(cs[i].y)-Sum(cs[i].x-1);
}
for(int i=L;i<=R;i++)
if(cs[i].kind==0&&cs[i].y<=mid)Add(cs[i].x,-cs[i].delta);
int totl=0,totr=0;
for(int i=L;i<=R;i++){
if(cs[i].kind==1){
//printf("%d %d %d %d\n",mid,cs[i].qpos,cs[i].cur+tmp[i],cs[i].k);
if(cs[i].cur+tmp[i]>=cs[i].k){
ql[totl++]=cs[i];
//printf("<<%d %d l:%d tot:%d %d %d %d\n",L,R,mid,cs[i].qpos,cs[i].x,cs[i].y,cs[i].k);
}
else {
cs[i].cur+=tmp[i];
qr[totr++]=cs[i];
//printf(">>%d %d r:%d tot:%d %d %d %d\n",L,R,mid,cs[i].qpos,cs[i].x,cs[i].y,cs[i].k);
}
}
else {
if(cs[i].y<=mid)ql[totl++]=cs[i];
else qr[totr++]=cs[i];
}
}
for(int i=0;i<totl;i++)cs[L+i]=ql[i];
for(int i=0;i<totr;i++)cs[L+totl+i]=qr[i];
//printf("%d %d %d %d-%d %d %d %d\n",L,totl-1,l,mid,L+totl,R,mid+1,r);
cdq(L,L+totl-1,l,mid);
cdq(L+totl,R,mid+1,r);
}
int main()
{
while(~scanf("%d",&n)){
int tot=0;
memset(C,0,sizeof(C));
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=n;i++){
scanf("%d",&A[i]);
cs[tot++]=point(i,A[i],0,0,0,1,0);
}
int qtot=0;
scanf("%d",&q);
for(int i=0,tp,l,r,x;i<q;i++){
scanf("%d",&tp);
if(tp==1){
scanf("%d%d",&l,&x);
cs[tot++]=point(l,A[l],0,0,0,-1,0);
A[l]=x;
cs[tot++]=point(l,A[l],0,0,0,1,0);
}
else {
scanf("%d%d%d",&l,&r,&x);
cs[tot++]=point(l,r,x,1,qtot++,0,0);
}
}
cdq(0,tot-1,0,1000000000+100);
for(int i=0;i<qtot;i++) printf("%d\n",ans[i]);
}
return 0;
}