zoukankan      html  css  js  c++  java
  • HDU

    题目链接

    动态区间第k小,但是这道题的话用主席树+树状数组套线段树的空间复杂度是O(nlog2n)会爆掉。

    另一种替代的方法是用树状数组套平衡树,空间复杂度降到了O(nlogn),但我感觉平衡树是个挺恶心的东西,而且时间复杂度是O(nlog3n),比主席树还多了个logn。

    最高效的方法是用一个叫整体二分的东西算法,它的基本思想是这样的:

    假设当前所有查询的答案范围都在[l,r]之间,设mid=(l+r)/2,那么我们只处理所有修改后的值在[l,mid]中的修改操作,把不需要执行的修改操作全部扔到后半区间,那么对于每个询问操作都可以知道它的答案是在[l,mid]之间还是(mid+1,r]之间,这样就把所有的询问划分到了两个独立的区间,然后递归处理即可。本质上是将原序列转化成01序列,这样处理起来就方便多了。与CDQ分治较为类似,是个很神奇的算法。

    空间复杂度O(n),时间复杂度O(nlog2n)

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 const int inf=0x3f3f3f3f;
     5 const int N=1e5+10;
     6 struct QR {
     7     int f,l,r,k,u,x,dx;
     8 } qr[N<<2];
     9 
    10 int a[N],c[N],b[N<<2],lq[N<<2],rq[N<<2],nq,tot,ans[N],n,m;
    11 int lowbit(int x) {return x&-x;}
    12 void add(int u,int x) {
    13     for(; u<=n; u+=lowbit(u))c[u]+=x;
    14 }
    15 int query(int u) {
    16     int ret=0;
    17     for(; u; u-=lowbit(u))ret+=c[u];
    18     return ret;
    19 }
    20 
    21 void solve(int l,int r,int L,int R) {
    22     if(L>R)return;
    23     if(l==r) {
    24         for(int i=L; i<=R; ++i)if(qr[b[i]].f)ans[qr[b[i]].u]=l;
    25         return;
    26     }
    27     int nl=0,nr=0,mid=(l+r)>>1;
    28     for(int i=L; i<=R; ++i) {
    29         if(!qr[b[i]].f) {
    30             if(qr[b[i]].x<=mid)add(qr[b[i]].u,qr[b[i]].dx),lq[nl++]=b[i];
    31             else rq[nr++]=b[i];
    32         } else {
    33             int t=query(qr[b[i]].r)-query(qr[b[i]].l-1);
    34             if(qr[b[i]].k<=t)lq[nl++]=b[i];
    35             else qr[b[i]].k-=t,rq[nr++]=b[i];
    36         }
    37     }
    38     for(int i=0; i<nl; ++i)if(!qr[lq[i]].f)add(qr[lq[i]].u,-qr[lq[i]].dx);
    39     for(int i=0; i<nl; ++i)b[L+i]=lq[i];
    40     for(int i=0; i<nr; ++i)b[L+nl+i]=rq[i];
    41     solve(l,mid,L,L+nl-1);
    42     solve(mid+1,r,L+nl,R);
    43 }
    44 
    45 int main() {
    46     while(scanf("%d",&n)==1) {
    47         nq=tot=0;
    48         memset(c,0,sizeof c);
    49         int maxn=0;
    50         for(int i=1; i<=n; ++i) {
    51             scanf("%d",&a[i]);
    52             maxn=max(maxn,a[i]);
    53             qr[nq++]=(QR) {0,0,0,0,i,a[i],1};
    54         }
    55         scanf("%d",&m);
    56         while(m--) {
    57             int f;
    58             scanf("%d",&f);
    59             if(f==1) {
    60                 int u,x;
    61                 scanf("%d%d",&u,&x);
    62                 qr[nq++]=(QR) {0,0,0,0,u,a[u],-1};
    63                 qr[nq++]=(QR) {0,0,0,0,u,a[u]=x,1};
    64                 maxn=max(maxn,a[u]);
    65             } else {
    66                 int l,r,k;
    67                 scanf("%d%d%d",&l,&r,&k);
    68                 qr[nq++]=(QR) {1,l,r,k,tot++,0,0};
    69             }
    70         }
    71         for(int i=0; i<nq; ++i)b[i]=i;
    72         solve(0,maxn,0,nq-1);
    73         for(int i=0; i<tot; ++i)printf("%d
    ",ans[i]);
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    寄存器基础知识
    基础知识
    架构
    Mac下Apache服务器的初步搭建
    ios字体简单设定
    xcode中自定义log打印
    jQuery打印插件
    ionic3生命周期钩子
    ES5 数组方法map
    $compile的妙用
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10286317.html
Copyright © 2011-2022 走看看