zoukankan      html  css  js  c++  java
  • 整体二分初识--POJ2104:K-th Number

    n<=100000个数有m<=5000个询问,每次问区间第k大。

    方法一:主席树!……

    方法二:整体二分。

    整体二分一次性计算半个值域对一个区间的询问的贡献,然后根据“这半边的贡献在某个询问中可不可以直接处理掉”把询问分两部分,并按“数字的值是否在这半边”把数字也分成两部分,这样把一个区间和值域都分掉了,然后就可以在f(n)logMax的时间出解,其中f(n)表示计算一次这样的贡献需要的时间。

    在这题里,只需要看某个区间里在值域[L,mid]中出现的数字的个数有没有到K个,以此划分成两个区域。因此树状数组搞一搞,f(n)=nlogn,大功告成。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 //#include<bitset>
     6 #include<algorithm>
     7 //#include<cmath>
     8 using namespace std;
     9 
    10 int n,m;
    11 #define maxn 200011
    12 const int inf=0x3f3f3f3f;
    13 struct App
    14 {
    15     int x,y,z,id,type;
    16     //type=1 表示修改,其中x为位置,y为数值,z为在bit中的修改权值 
    17     //type=0 表示询问,其中x,y为左右端点,z是第几大,id询问编号 
    18 }a[maxn],al[maxn],ar[maxn];
    19 int ans[maxn];
    20 
    21 struct BIT
    22 {
    23     int a[maxn];
    24     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
    25     int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;}
    26 }t;
    27 
    28 void solve(int L,int R,int ql,int qr)
    29 {
    30     if (ql>qr || L>R) return;
    31     if (L==R)
    32     {
    33         for (int i=ql;i<=qr;i++) ans[a[i].id]=L;
    34         return;
    35     }
    36     const int mid=(L+R)>>1;
    37     int lal=0,lar=0;
    38     for (int i=ql;i<=qr;i++)
    39     {
    40         if (a[i].type)
    41         {
    42             if (a[i].y<=mid)
    43             {
    44                 t.add(a[i].x,a[i].z);
    45                 al[++lal]=a[i];
    46             }
    47             else ar[++lar]=a[i];
    48         }
    49         else
    50         {
    51             int tmp=t.query(a[i].y)-t.query(a[i].x-1);
    52             if (tmp>=a[i].z) al[++lal]=a[i];
    53             else
    54             {
    55                 ar[++lar]=a[i];
    56                 ar[lar].z-=tmp;
    57             }
    58         }
    59     }
    60     for (int i=1;i<=lal;i++) if (al[i].type==1) t.add(al[i].x,-al[i].z);
    61     for (int i=1,j=ql;i<=lal;i++,j++) a[j]=al[i];
    62     for (int i=1,j=ql+lal;i<=lar;i++,j++) a[j]=ar[i];
    63     solve(L,mid,ql,ql+lal-1);
    64     solve(mid+1,R,ql+lal,qr);
    65 }
    66 
    67 int main()
    68 {
    69     scanf("%d%d",&n,&m);
    70     for (int i=1;i<=n;i++) scanf("%d",&a[i].y),a[i].x=i,a[i].z=1,a[i].type=1;
    71     for (int i=1,j=n+1;i<=m;i++,j++) scanf("%d%d%d",&a[j].x,&a[j].y,&a[j].z),a[j].id=i,a[j].type=0;
    72     solve(-inf,inf,1,n+m);
    73     for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    这篇文章把短线操作技巧以及交易原则讲透了!
    炒股老手的妙招——卖出在周K线的顶部
    连续多阳低吸买入法需要哪些条件?
    2个实盘案例带你了解南玻量态选庄股法!
    如何通过筹码分布判断一个股票要不要做?
    股票指标公式高手是怎么通过指标变现的?
    股票回踩均线是什么意思?
    定宽不定宽盒子的居中解决办法和外边距塌陷问题
    JS 数据类型
    JS 事件总结
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8203399.html
Copyright © 2011-2022 走看看