【bzoj 3110】[Zjoi2013]K大数查询
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c。如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M。
接下来M行,每行形如1 a b c或2 a b c。
Output
输出每个询问的结果。
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
HINT
【样例说明】
第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3大的数是 1 。
N,M<=50000,N,M<=50000,a<=b<=N,1操作中abs(c)<=N,2操作中c<=Maxlongint。
整体二分裸题……顺便可以了解一下用树状数组实现区间加和区间求和操作。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #define LL long long 6 using namespace std; 7 const int N=1e5+5; 8 int n,m,qid,mx,ans[N]; 9 LL tr[N][2]; 10 bool f[N]; 11 struct node{int op,l,r,c,id;}a[N],tmp[N]; 12 LL read() 13 { 14 LL x=0,f=1;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 16 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 17 return x*f; 18 } 19 int lowbit(int x){return x&(-x);} 20 void add(int x,LL c,int id){while(x<=n)tr[x][id]+=c,x+=lowbit(x);} 21 void insert(int id,LL c){add(id,c,0);add(id,c*id,1);} 22 LL query(int x,int id){LL ans=0;while(x)ans+=tr[x][id],x-=lowbit(x);return ans;} 23 LL ask(int id){LL ans=(id+1)*query(id,0)-query(id,1);return ans;} 24 void work(int x,int y,int l,int r) 25 { 26 if(l==r){for(int i=x;i<=y;i++)if(a[i].op==2)ans[a[i].id]=l;return;} 27 int h1=x,h2=x,mid=(l+r)>>1; 28 for(int i=x;i<=y;i++) 29 if(a[i].op==2) 30 { 31 LL temp=ask(a[i].r)-ask(a[i].l-1); 32 if(temp<a[i].c)f[i]=false,a[i].c-=temp; 33 else f[i]=true,h2++; 34 } 35 else if(a[i].c<=mid)insert(a[i].l,1),insert(a[i].r+1,-1),f[i]=true,h2++; 36 else f[i]=false; 37 for(int i=x;i<=y;i++)if(a[i].op==1&&a[i].c<=mid)insert(a[i].l,-1),insert(a[i].r+1,1); 38 for(int i=x;i<=y;i++)if(f[i])tmp[h1++]=a[i];else tmp[h2++]=a[i]; 39 for(int i=x;i<=y;i++)a[i]=tmp[i]; 40 work(x,h1-1,l,mid);work(h1,y,mid+1,r); 41 } 42 int main() 43 { 44 n=read();m=read(); 45 for(int i=1;i<=m;i++) 46 { 47 a[i].op=read();a[i].l=read();a[i].r=read();a[i].c=read(); 48 if(a[i].op==1)a[i].c=n-a[i].c+1,mx=max(mx,a[i].c); 49 else a[i].id=++qid; 50 } 51 work(1,m,1,mx); 52 for(int i=1;i<=qid;i++)printf("%d\n",n-ans[i]+1); 53 return 0; 54 }