zoukankan      html  css  js  c++  java
  • 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
    ",-ans[i]);
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    jQuery获取当前元素是该父元素的第几个元素&获取父元素的第n个子元素
    获取当前月份的天数
    获取当年的每个月份的天数:
    解决ul下的li换行问题,(父元素div加overflow:scroll没作用的问题)
     获取当年的月份的天数:
    程序员成长道路上必经的几个阶段
    CSS如何让文字垂直居中?
    2015年7个重要的Web设计趋势
    引入css文件时,css link和@import区别
    在html页面引用css文件的方法
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8240866.html
Copyright © 2011-2022 走看看