传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1901
一道被暴力、树套树、主席树、分块、整体二分、划分树以及各种奇怪的方法完艹的经典题目
拿来练习一下整体二分
用好stl感觉整个人都萌萌哒!!
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10005;
int d[maxn];
int n,m;
int a[maxn];
int lowbit(int x){
return x&-x;
}
int get(int x){
int ans=0;
while(x)ans+=d[x],x-=lowbit(x);
return ans;
}
void updata(int x,int y){
while(x<=n)d[x]+=y,x+=lowbit(x);
}
struct qes{
int x,y,z,ty,ind,cur,delta;
}q[maxn*3];
int cnt=0,anss[maxn],tmp[maxn],md,mx;
bool part(qes &Q){
if(Q.ty==3){
if(Q.cur+Q.delta>Q.z-1)return true;
Q.cur+=Q.delta;Q.delta=0;return false;
}return Q.y<=md;
}
void solve(int lef,int rig,int l,int r){
if(lef>rig)return;
if(l==r){
for(int i=lef;i<=rig;i++)if(q[i].ty==3)
anss[q[i].ind]=l;return;
}int mid=(l+r)>>1;md=mid;
for(int i=lef;i<=rig;i++){
if(q[i].ty==1&&q[i].y<=mid)updata(q[i].x,1);
if(q[i].ty==2&&q[i].y<=mid)updata(q[i].x,-1);
if(q[i].ty==3)q[i].delta=get(q[i].y)-get(q[i].x-1);
}
for(int i=lef;i<=rig;i++){
if(q[i].ty==1&&q[i].y<=mid)updata(q[i].x,-1);
if(q[i].ty==2&&q[i].y<=mid)updata(q[i].x,1);
}
int dv=stable_partition(q+lef,q+rig+1,part)-q-1;
solve(lef,dv,l,mid);
solve(dv+1,rig,mid+1,r);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);mx=max(mx,a[i]);
q[++cnt]=(qes){i,a[i],0,1,0,0,0};
}for(int i=1;i<=m;i++){
char op=getchar();while(op!='Q'&&op!='C')op=getchar();
if(op=='Q'){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
q[++cnt]=(qes){l,r,k,3,++anss[0],0,0};
}else{
int x,y;
scanf("%d%d",&x,&y);
q[++cnt]=(qes){x,a[x],0,2,0,0,0};
q[++cnt]=(qes){x,y,0,1,0,0,0};
a[x]=y;mx=max(mx,a[x]);
}
}
solve(1,cnt,0,mx);
for(int i=1;i<=anss[0];i++)printf("%d\n",anss[i]);
return 0;
}