BZOJ_3110_[Zjoi2013]K large number query_overall bisection + tree array
Description
There are N positions, M operations. There are two kinds of operations. If each operation is in the form of 1 abc, it means from the ath position to the bth position, and a number c is added to each position.
If it is in the form of 2 abc, it means that the query is from the ath position to the bth position. position, what is the C-th largest number.
Input
The first line N, M
next M lines, each line is like 1 abc or 2 abc
Output
output the result of each query
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
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
2
1
solve(b,e,l,r) means to process the query of b~e, the answer is between l~r, and the insertion is processed at the same time, and the weight range is l~r.
Take all operations offline, while keeping operations in timestamp order at any time.
The two-point answer mid, if the inserted number is greater than mid, insert it (interval addition), otherwise throw it to the left.
For the query like a normal overall bisection, query the interval sum, and then go left or right.
Code:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef unsigned int uint; #define N 50050 int n, m, flg [N], ans [N]; struct Bit { uint c[N]; void fix(int x,uint v) { for(;x<=n;x+=x&(-x)) c[x]+=v; } uint inq(int x) { uint re=0;for(;x;x-=x&(-x)) re+=c[x];return re;} }A,B; struct Q { int a,b,c,d,id; }q[N],t[N]; void update(int x,int y,uint v) { A.fix(x,v); A.fix(y+1,-v); B.fix(x,x*v); B.fix(y+1,-(y+1)*v); } uint query(int x,int y) { return A.inq(y)*(y+1)-B.inq(y)-A.inq(x-1)*x+B.inq(x-1); } void solve(int b,int e,int l,int r) { int i; if(b>e) return ; if(l==r) { for(i=b;i<=e;i++) if(q[i].a==2) ans[q[i].id]=l; return ; } int mid=(l+r)>>1,lp=b-1,rp=e+1; for(i=b;i<=e;i++) { if(q[i].a==1) { if(q[i].d<=mid) t[++lp]=q[i]; else update(q[i].b,q[i].c,1),t[--rp]=q[i]; }else { uint tmp=query(q[i].b,q[i].c); if(q[i].d<=tmp) t[--rp]=q[i]; else q[i].d-=tmp,t[++lp]=q[i]; } } for(i=b;i<=e;i++) { if(q[i].a==1&&q[i].d>mid) update(q[i].b,q[i].c,-1); } for(i=b;i<=lp;i++) q[i]=t[i]; for(i=rp;i<=e;i++) q[e-i+rp]=t[i]; solve(b,lp,l,mid); solve(rp,e,mid+1,r); } int main() { scanf("%d%d",&n,&m); int i; for(i=1;i<=m;i++) { scanf("%d%d%d%d",&q[i].a,&q[i].b,&q[i].c,&q[i].d); q[i].id=i; if(q[i].a==2) flg[i]=1; } solve(1,m,-n,n); for(i=1;i<=m;i++) if(flg[i]) printf("%d\n",ans[i]); }