【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树

外面是树状数组,里面是动态开点线段树,对于查询我们先把有关点找出来,然后一起在线段树上行走,这样就是单个O(log2)的了

#include <cstdio>
#include <vector>
#include <cstring>
#define R register
#define Inf 1000000000
#define MAXN 50000
using namespace std;
inline int read()
{
  R int sum=0;
  R char ch=getchar();
  while(ch<'0'||ch>'9')ch=getchar();
  while(ch>='0'&&ch<='9')
  {
    sum=(sum<<1)+(sum<<3)+ch-'0';
    ch=getchar();
  }
  return sum;
}
struct Seg_Tree
{
  Seg_Tree *ch[2];
  int l,r,size;
  void pushup()
  {
    size=ch[0]->size+ch[1]->size;
  }
}*null,*root[MAXN+10];
typedef vector<Seg_Tree*> S;
char s[1];
int a[MAXN+10];
inline Seg_Tree *New(int l,int r)
{
  Seg_Tree *p=new Seg_Tree;
  p->l=l,p->r=r,p->size=0;
  p->ch[0]=p->ch[1]=null;
  return p;
}
int n,m;
void ins(Seg_Tree *p,int key)
{
  if(p->l==p->r)
  {
    p->size++;
    return;
  }
  if(key<=((p->l+p->r)>>1))
  {
    if(p->ch[0]==null)p->ch[0]=New(p->l,((p->l+p->r)>>1));
    ins(p->ch[0],key);
  }
  else
  {
    if(p->ch[1]==null)p->ch[1]=New(((p->l+p->r)>>1)+1,p->r);
    ins(p->ch[1],key);
  }
  p->pushup();
}
inline void Ins(int pos,int key)
{
  while(pos<=n)
  {
    if(root[pos]==null)root[pos]=New(0,Inf);
    ins(root[pos],key);
    pos+=pos&(-pos);
  }
}
void del(Seg_Tree *&p,int key)
{
  if(p->l==p->r)
  {
    p->size--;
    if(p->size==0){ delete p; p=null; }
    return;
  }
  if(key<=((p->l+p->r)>>1))del(p->ch[0],key);
  else del(p->ch[1],key);
  p->pushup();
  if(p->size==0){ delete p; p=null; }
}
inline void Del(int pos,int key)
{
  while(pos<=n)
  {
    del(root[pos],key);
    pos+=pos&(-pos);
  }
}
inline void Init()
{
  null=New(0,0),n=read(),m=read();
  null->ch[0]=null->ch[1]=null;
  for(R int i=1;i<=n;i++)root[i]=null;
  for(R int i=1;i<=n;i++)
    a[i]=read(),Ins(i,a[i]);
}
inline S Catch(int pos)
{
  S v;v.clear();
  while(pos)
  {
    v.push_back(root[pos]);
    pos-=pos&(-pos);
  }
  return v;
}
inline S get_ch0(S v)
{
  for(R int i=0;i<v.size();++i)v[i]=v[i]->ch[0];
  return v; 
}
inline S get_ch1(S v)
{
  for(R int i=0;i<v.size();++i)v[i]=v[i]->ch[1];
  return v; 
}
int query(S v1,S v2,int k,int z,int y)
{
  if(z==y)return z;
  R int sum=0;
  for(int i=0;i<v2.size();i++)sum+=v2[i]->ch[0]->size;
  for(int i=0;i<v1.size();i++)sum-=v1[i]->ch[0]->size;
  if(sum>=k) return query(get_ch0(v1),get_ch0(v2),k,z,(z+y)>>1);
  else return query(get_ch1(v1),get_ch1(v2),k-sum,((z+y)>>1)+1,y);
}
inline void Work()
{
  R int x,y,z;
  while(m--)
  {
    scanf("%s",s);
    if(s[0]=='C')
    {
      x=read(),y=read();
      Del(x,a[x]),Ins(x,y);
      a[x]=y;
      continue;
    }
    else
    {
      x=read(),y=read(),z=read();
      printf("%d\n",query(Catch(x-1),Catch(y),z,0,Inf));
    }
  }
}
void CL(Seg_Tree *p)
{
  if(p==null)return;
  CL(p->ch[0]);
  CL(p->ch[1]);
  delete p;
}
inline void Clear()
{
  for(int i=1;i<=n;i++)CL(root[i]),root[i]=NULL;
  delete null;null=NULL;
}
int main()
{
  freopen("dynrank.in","r",stdin);
  freopen("dynrank.out","w",stdout);
  R int T=read();
  while(T--)
  {
    Init();
    Work();
    Clear();
  }
}

 

posted @ 2017-08-03 13:20  TS_Hugh  阅读(...)  评论(...编辑  收藏