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 }

 

posted @ 2016-03-22 08:41  HugeGun  阅读(188)  评论(0编辑  收藏  举报