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\n",ask(data[i].l,data[i].r,data[i].k));

                        break;

                    }

              }

        }

      return 0;

  }
View Code

 

你可能感兴趣的:(ZOJ)