bzoj3110 [Zjoi2013]K大数查询
showson教我整体二分。。。
为什么我跑的时间是他的2倍呢?我sort了结构体。。。
二分权值(答案),把 询问和操作 按要求的权值分在左边或右边;
当二分的权值范围为1时,当前的所有询问 的答案都是这个二分出来的东西
判断往哪边放就用线段树区间修改区间查询,记得清空。。。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<queue> 10 #include<stack> 11 #include<map> 12 #include<set> 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--) 14 #define re(i,l,r) for(int i=(l);i<=(r);i++) 15 #define Clear(a,b) memset(a,b,sizeof(a)) 16 #define inout(x) printf("%d",(x)) 17 #define douin(x) scanf("%lf",&x) 18 #define strin(x) scanf("%s",(x)) 19 #define LLin(x) scanf("%lld",&x) 20 #define op operator 21 #define CSC main 22 typedef unsigned long long ULL; 23 typedef const int cint; 24 typedef long long LL; 25 using namespace std; 26 void inin(int &ret) 27 { 28 ret=0;int f=0;char ch=getchar(); 29 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 30 while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar(); 31 ret=f?-ret:ret; 32 } 33 struct wocao 34 { 35 int opt,l,r,x,id,lei; 36 bool op < (const wocao &a)const {return lei==a.lei?id<a.id:lei<a.lei;} 37 }a[50050]; 38 int n,m,ans[50050]; 39 namespace seg 40 { 41 int l[400020],r[400020],add[400020]; 42 LL sum[400020]; 43 void build(int k,int ll,int rr) 44 { 45 r[k]=rr,l[k]=ll; 46 if(ll==rr)return ; 47 int mid=(ll+rr)>>1,p1=k<<1,p2=p1|1; 48 build(p1,ll,mid),build(p2,mid+1,rr); 49 } 50 void down(int x) 51 { 52 int p1=x<<1,p2=p1|1; 53 if(add[x]) 54 { 55 sum[p1]+=1LL*add[x]*(r[p1]-l[p1]+1); 56 sum[p2]+=1LL*add[x]*(r[p2]-l[p2]+1); 57 add[p1]+=add[x],add[p2]+=add[x]; 58 add[x]=0; 59 } 60 } 61 void change(int k,int ll,int rr,int x) 62 { 63 down(k); 64 if(r[k]<=rr&&l[k]>=ll){sum[k]+=x*(r[k]-l[k]+1),add[k]+=x;return ;} 65 int mid=(l[k]+r[k])>>1,p1=k<<1,p2=p1|1; 66 if(rr<=mid)change(p1,ll,rr,x); 67 else if(ll>mid)change(p2,ll,rr,x); 68 else change(p1,ll,rr,x),change(p2,ll,rr,x); 69 sum[k]=sum[p1]+sum[p2]; 70 } 71 LL query(int k,int ll,int rr) 72 { 73 down(k); 74 if(r[k]<=rr&&l[k]>=ll)return sum[k]; 75 int mid=(r[k]+l[k])>>1,p1=k<<1,p2=p1|1; 76 if(rr<=mid)return query(p1,ll,rr); 77 if(ll>mid)return query(p2,ll,rr); 78 return query(p1,ll,rr)+query(p2,ll,rr); 79 } 80 } 81 void solve(int l,int r,int vl,int vr) 82 { 83 if(l>r)return ; 84 if(vl==vr) 85 { 86 re(i,l,r)if(a[i].opt==2)ans[a[i].id]=vl; 87 return ; 88 } 89 int vm=(vl+vr)>>1,t=l-1; 90 re(i,l,r) 91 { 92 if(a[i].opt==1) 93 if(a[i].x>vm)seg::change(1,a[i].l,a[i].r,1),a[i].lei=1; 94 else a[i].lei=0,t++; 95 else 96 { 97 LL pp=seg::query(1,a[i].l,a[i].r); 98 if(a[i].x<=pp)a[i].lei=1; 99 else t++,a[i].lei=0,a[i].x-=pp; 100 } 101 } 102 re(i,l,r) 103 if(a[i].opt==1) 104 if(a[i].x>vm)seg::change(1,a[i].l,a[i].r,-1); 105 sort(a+l,a+r+1); 106 solve(l,t,vl,vm),solve(t+1,r,vm+1,vr); 107 } 108 int main() 109 { 110 inin(n),inin(m); 111 seg::build(1,1,n); 112 re(i,1,m)inin(a[i].opt),inin(a[i].l),inin(a[i].r),inin(a[i].x),a[i].id=i; 113 solve(1,m,1,n); 114 re(i,1,m)if(ans[i])printf("%d\n",ans[i]); 115 return 0; 116 }