zoukankan      html  css  js  c++  java
  • zoj2112

    题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112

    经典的动态区间第K大。
    用树状数组套线段树。
    对原数组建一个树状数组,每个树状数组的结点代表一个线段树,这个线段树以权值为下标,包括这个树状数组的结点包含的区间。
    插入的时候可以由树状数组和线段树写法类比,只与logn棵线段树有关,每棵线段树用时logn,总共的时间复杂度n*logn^2。
    询问[l,r]的时候,类似与前缀和,找到与l-1有关的logn棵线段树,找到与人有关的logn棵线段树,然后类似于静态区间第K大,判断是往左子树还是右子树,有2logn棵线段树,判断往左子树还是右子树logn次,总共的时间复杂度n*logn^2。
    网址上空间比较小,这个程序会MLE。
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b)  for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxN=50000;
    const int maxM=10000;
    const int maxcnt=maxN+maxM;
    
    int N,M;
    int a[maxN+100];
    struct Tdata
      {
          char type;
          int l,r,k,t;
          inline void input()
            {
                type=getchar();while(!(type=='C' || type=='Q'))type=getchar();
                if(type=='Q'){l=gint();r=gint();k=gint();}else{l=gint();t=gint();}
            }
        }data[maxM+100];
        
    int bak[maxcnt+100],cnt;
    
    struct Tnode{int son[2],val;}sn[maxcnt*100+10000];int idx;
    int tree[maxN+100];
    
    inline int newnode(){++idx;sn[idx].son[0]=sn[idx].son[1]=sn[idx].val=0;return idx;}
    inline void update(int p,int l,int r,int x,int val)
      {
          while(1)
            {
                sn[p].val+=val;
                if(l==r)break;
                int mid=(l+r)/2;
                int f=(x>mid);
                if(!sn[p].son[f])sn[p].son[f]=newnode();
                if(x<=mid){p=sn[p].son[0];r=mid;}else{p=sn[p].son[1];l=mid+1;}
            }
      }
    
    #define lowbit(a) (a&(-a))
    inline void change(int a,int x,int val)
      {
          for(;a<=N;a+=lowbit(a))
              update(tree[a],1,cnt,x,val);
        }
    
    
    int lge,larr[maxN+100],rge,rarr[maxN+100];
    inline int ask(int l,int r,int k)
      {
          int i;
          l--;
          lge=0;
          for(;l>=1;l-=lowbit(l))larr[++lge]=tree[l];
          rge=0;
          for(;r>=1;r-=lowbit(r))rarr[++rge]=tree[r];
          int x=1,y=cnt;
          while(1)
            {
                if(x==y)return bak[x];
                int mid=(x+y)/2,G=0;
                re(i,1,rge)G+=sn[sn[rarr[i]].son[0]].val;
                re(i,1,lge)G-=sn[sn[larr[i]].son[0]].val;
                if(G<k)
                  {
                      k-=G;
                      x=mid+1;
                      re(i,1,rge)rarr[i]=sn[rarr[i]].son[1];
                      re(i,1,lge)larr[i]=sn[larr[i]].son[1];
                  }
                else
                  {
                      y=mid;
                      re(i,1,rge)rarr[i]=sn[rarr[i]].son[0];
                      re(i,1,lge)larr[i]=sn[larr[i]].son[0];
                  }
            }
      }
    
    int main()
      {
          freopen("zoj2112.in","r",stdin);
          freopen("zoj2112.out","w",stdout);
          int i;
          for(int Case=gint();Case;Case--)
            {
                N=gint();M=gint();
                re(i,1,N)a[i]=gint();
                re(i,1,M)data[i].input();
                cnt=0;
                re(i,1,N)bak[++cnt]=a[i];
                re(i,1,M)if(data[i].type=='C')bak[++cnt]=data[i].t;
                sort(bak+1,bak+cnt+1);
                cnt=unique(bak+1,bak+cnt+1)-bak-1;
                re(i,1,N)a[i]=lower_bound(bak+1,bak+cnt+1,a[i])-bak;
                re(i,1,M)if(data[i].type=='C')data[i].t=lower_bound(bak+1,bak+cnt+1,data[i].t)-bak;
                idx=0;
                re(i,0,N)tree[i]=newnode();
                re(i,1,N)change(i,a[i],1);
                re(i,1,M)
                  {
                      int x;
                      switch(data[i].type)
                        {
                            case 'C':
                                x=data[i].l;
                                change(x,a[x],-1);
                                a[x]=data[i].t;
                                change(x,a[x],1);
                            break;
                            case 'Q':
                                printf("%d
    ",ask(data[i].l,data[i].r,data[i].k));
                            break;
                        }
                  }
            }
          return 0;
      }
    View Code
  • 相关阅读:
    『空』
    退役前的做题记录 Ⅰ
    BZOJ3600 没有人的算术(替罪羊树,线段树)
    洛谷P5324 [BJOI2019]删数(线段树)
    洛谷P4696 [CEOI2011]Matching(KMP)
    Leetcode 638 大礼包 DP
    Leetcode 86 分割链表
    Leetcode 71 简化路径
    Leetcode 17.15 最长单词 剪枝与记忆化
    Leetcode 17.22单词转换 dfs+回溯+剪枝
  • 原文地址:https://www.cnblogs.com/maijing/p/4649483.html
Copyright © 2011-2022 走看看