bzoj 3110 K大数查询
第一道整体二分,因为只需要知道每个询问区间中比mid大的数有多少个,就可以直接用线段树区间加,区间求和了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 #define N 50005 7 #define ls x*2,l,mid 8 #define rs x*2+1,mid+1,r 9 using namespace std; 10 int n,m; 11 struct node 12 { 13 int sign,x,y,c; 14 }op[N]; 15 int q[N],ans[N]; 16 int a[N*8],lazy[N*8]; 17 void push_down(int x,int l,int mid,int r) 18 { 19 if(lazy[x]!=0) 20 { 21 lazy[x*2]+=lazy[x]; 22 lazy[x*2+1]+=lazy[x]; 23 a[x*2]+=lazy[x]*(mid-l+1); 24 a[x*2+1]+=lazy[x]*(r-mid); 25 lazy[x]=0; 26 } 27 return ; 28 } 29 int qur(int x,int l,int r,int ll,int rr) 30 { 31 if(l>=ll&&r<=rr)return a[x]; 32 int mid=(l+r)>>1; 33 push_down(x,l,mid,r); 34 if(rr<=mid)return qur(ls,ll,rr); 35 if(ll>mid)return qur(rs,ll,rr); 36 return qur(ls,ll,rr)+qur(rs,ll,rr); 37 } 38 void gai(int x,int l,int r,int ll,int rr,int d) 39 { 40 if(l>=ll&&r<=rr) 41 { 42 lazy[x]+=d; 43 a[x]+=d*(r-l+1); 44 return ; 45 } 46 int mid=(l+r)>>1; 47 push_down(x,l,mid,r); 48 if(ll<=mid)gai(ls,ll,rr,d); 49 if(rr>mid)gai(rs,ll,rr,d); 50 a[x]=a[x*2]+a[x*2+1]; 51 } 52 int tmp[2][N]; 53 void solve(int L,int R,int l,int r) 54 { 55 if(L>R)return ; 56 if(l==r) 57 { 58 for(int i=L;i<=R;i++)if(op[q[i]].sign==2)ans[q[i]]=l; 59 return ; 60 } 61 int mid=(l+r)>>1; 62 int cnt1=0,cnt2=0; 63 for(int i=L;i<=R;i++) 64 { 65 if(op[q[i]].sign==1) 66 { 67 if(op[q[i]].c>mid) 68 { 69 gai(1,1,n,op[q[i]].x,op[q[i]].y,1); 70 tmp[1][++cnt2]=q[i]; 71 } 72 else tmp[0][++cnt1]=q[i]; 73 } 74 else 75 { 76 int y=qur(1,1,n,op[q[i]].x,op[q[i]].y); 77 if(y>=op[q[i]].c) 78 { 79 tmp[1][++cnt2]=q[i]; 80 } 81 else op[q[i]].c-=y,tmp[0][++cnt1]=q[i]; 82 } 83 } 84 for(int i=L;i<=R;i++) 85 { 86 if(op[q[i]].sign==1) 87 { 88 if(op[q[i]].c>mid)gai(1,1,n,op[q[i]].x,op[q[i]].y,-1); 89 } 90 } 91 int l1=L+cnt1-1; 92 for(int i=1;i<=cnt1;i++)q[L+i-1]=tmp[0][i]; 93 for(int i=1;i<=cnt2;i++)q[l1+i]=tmp[1][i]; 94 solve(L,l1,l,mid);solve(l1+1,R,mid+1,r); 95 } 96 signed main() 97 { 98 scanf("%lld%lld",&n,&m); 99 for(int i=1;i<=m;i++) 100 { 101 scanf("%lld%lld%lld%lld",&op[i].sign,&op[i].x,&op[i].y,&op[i].c); 102 q[i]=i; 103 } 104 solve(1,m,1,n); 105 for(int i=1;i<=m;i++) 106 { 107 if(op[i].sign==2)printf("%lld\n",ans[i]); 108 } 109 return 0; 110 }