BZOJ3110: [Zjoi2013]K大数查询

n<=50000个vector进行m<=50000次操作:1、一区间的vector插入一个数;2、查询一区间中的vector中的所有数的第k大。

方法一:普通线段树套权值线段树!……

方法二:单个询问是可以二分的,那就整体二分吧。这次是用线段树维护,把所有数字反过来求第k小再反过来就是第k大,注意50000*50000>int。

  1 #include<string.h>
  2 #include<stdlib.h>
  3 #include<stdio.h>
  4 //#include<assert.h>
  5 #include<algorithm>
  6 //#include<iostream>
  7 using namespace std;
  8 
  9 int n,m;
 10 #define maxn 100011
 11 #define LL long long
 12 struct Ope
 13 {
 14     int x,y; LL z; int id,type;
 15     //type=1:xiugai,[x,y] ba zhi z jia 1
 16     //type=0:chaxun,[x,y] cha di z da,xunwen bian hao id
 17 }q[maxn],al[maxn],ar[maxn];int len=0;
 18 int ans[maxn];
 19 
 20 struct SMT
 21 {
 22     struct Node
 23     {
 24         int ls,rs;
 25         int add; LL sum;
 26     }a[maxn<<1];
 27     int size,root;
 28     void clear() {size=root=0;}
 29     void up(int x)
 30     {
 31         const int &p=a[x].ls,&q=a[x].rs;
 32         a[x].sum=a[p].sum+a[q].sum;
 33     }
 34     void addsingle(int x,int L,int R,int v)
 35     {
 36         a[x].sum+=(R-L+1)*1ll*v;
 37         a[x].add+=v;
 38     }
 39     void down(int x,int L,int R)
 40     {
 41         int mid=(L+R)>>1,&p=a[x].ls,&q=a[x].rs;
 42         if (!p) {p=++size; a[p].ls=a[p].rs=a[p].sum=a[p].add=0;}
 43         if (!q) {q=++size; a[q].ls=a[q].rs=a[q].sum=a[q].add=0;}
 44         if (a[x].add) addsingle(p,L,mid,a[x].add),addsingle(q,mid+1,R,a[x].add),a[x].add=0;
 45     }
 46     int ql,qr,v;
 47     void Add(int &x,int L,int R)
 48     {
 49         if (!x) {x=++size; a[x].add=a[x].sum=a[x].ls=a[x].rs=0;}
 50         if (ql<=L && R<=qr) {addsingle(x,L,R,v); return;}
 51         down(x,L,R);
 52         const int mid=(L+R)>>1;
 53         if (ql<=mid) Add(a[x].ls,L,mid+0);
 54         if (qr> mid) Add(a[x].rs,mid+1,R);
 55         up(x);
 56     }
 57     void add(int L,int R,int v)
 58     {
 59         ql=L; qr=R; this->v=v;
 60         Add(root,1,n);
 61     }
 62     LL Query(int &x,int L,int R)
 63     {
 64         if (!x) {x=++size; a[x].add=a[x].sum=a[x].ls=a[x].rs=0;}
 65         if (ql<=L && R<=qr) return a[x].sum;
 66         down(x,L,R);
 67         const int mid=(L+R)>>1; LL ans=0;
 68         if (ql<=mid) ans+=Query(a[x].ls,L,mid+0);
 69         if (qr> mid) ans+=Query(a[x].rs,mid+1,R);
 70         return ans;
 71     }
 72     LL query(int L,int R)
 73     {
 74         ql=L; qr=R;
 75         return Query(root,1,n);
 76     }
 77 }t;
 78 
 79 void solve(int L,int R,int ql,int qr)
 80 {
 81     if (L>R || ql>qr) return;
 82     if (L==R)
 83     {
 84         for (int i=ql;i<=qr;i++) if (q[i].type==0) ans[q[i].id]=L;
 85         return;
 86     }
 87     t.clear();
 88     int mid=(L+R)>>1,lal=0,lar=0;
 89     for (int i=ql;i<=qr;i++)
 90     {
 91         if (q[i].type==1)
 92         {
 93             if (q[i].z<=mid) t.add(q[i].x,q[i].y,1),al[++lal]=q[i];
 94             else ar[++lar]=q[i];
 95         }
 96         else
 97         {
 98             LL tmp=t.query(q[i].x,q[i].y);
 99             if (tmp>=q[i].z) al[++lal]=q[i];
100             else q[i].z-=tmp,ar[++lar]=q[i];
101         }
102     }
103     for (int i=1,j=ql;i<=lal;i++,j++) q[j]=al[i];
104     for (int i=1,j=ql+lal;i<=lar;i++,j++) q[j]=ar[i];
105     solve(L,mid,ql,ql+lal-1);
106     solve(mid+1,R,ql+lal,qr);
107 }
108 
109 int main()
110 {
111     scanf("%d%d",&n,&m);
112     int cntq=0;
113     for (int i=1,op;i<=m;i++)
114     {
115         scanf("%d",&op);
116         if (op==1) len++,scanf("%d%d%lld",&q[len].x,&q[len].y,&q[len].z),q[len].z*=-1,q[len].type=1;
117         else len++,scanf("%d%d%lld",&q[len].x,&q[len].y,&q[len].z),q[len].id=++cntq,q[len].type=0;
118     }
119     solve(-n,n,1,len);
120     for (int i=1;i<=cntq;i++) printf("%d\n",-ans[i]);
121     return 0;
122 }
View Code

 

posted @ 2018-01-08 07:36  Blue233333  阅读(170)  评论(0编辑  收藏  举报