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

 

posted @ 2015-07-15 21:01  maijing  阅读(319)  评论(0编辑  收藏  举报