您的位置:首页 > 其它

BZOJ-3065 带插入区间K小值

2015-04-21 20:20 417 查看
这道题为树套树,我自己是替罪羊树套权值线段树。

此题有三种操作:

1.询问K值:可通过替罪羊树提取区间+权值线段树合并+二分答案求得

2.修改:可通过权值线段树的删除+添加操作实现

3.插入:可通过替罪羊树的插入操作实现

#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cctype>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define clr(x, c) memset(x, c, sizeof(x))
#define inf 0x7fffffff
#define ll long long
#define maxn 80010
#define maxl 70010

#define l(x) Left[x]
#define r(x) Right[x]
#define s(x) Size[x]
#define k(x) Key[x]
#define t(x) Tree[x]
#define ls(x) Size[Left[x]]
#define rs(x) Size[Right[x]]
#define a 0.8

using namespace std;
inline int read()
{
int x=0, f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
return x*f;
}

//=========================================================================================

struct node
{
node *l, *r; int sum;
node () {sum=0; l=r=NULL;}
} *blank=new(node);
void Add(int l, int r, int k, node*&t)
{
if (t==blank) t=new(node), t->l=t->r=blank;
t->sum++;
if (l==r) return; int mid=(l+r)>>1;
if (k<=mid) Add(l, mid, k, t->l); else Add(mid+1, r, k, t->r);
}
void Del(int l, int r, int k, node*&t)
{
t->sum--;
if (l==r) return; int mid=(l+r)>>1;
if (k<=mid) Del(l, mid, k, t->l); else Del(mid+1, r, k, t->r);
}

//=========================================================================================

int Left[maxn], Right[maxn], Key[maxn], Size[maxn], V=0, roof, dfn[maxn], top;
node *Tree[maxn];
void Build(int l, int r, int &t)
{
if (l>r) {t=0; return;}
int mid=(l+r)>>1;
t=dfn[mid], t(t)=blank, s(t)=r-l+1;
rep(i, l, r) Add(0, maxl, k(dfn[i]), t(t));
Build(l, mid-1, l(t)), Build(mid+1, r, r(t));
}
node *range[maxn];
int p[maxn], nr, np;
void ranging(int l, int r, int t) //BST查找区间
{
if (r<ls(t)) ranging(l, r, l(t));  //全在左边
else if (l>ls(t)) ranging(l-ls(t)-1, r-ls(t)-1, r(t)); //全在右边
else if (!l && r==s(t)-1) range[++nr]=t(t); //整棵树都是
else //分跨两边
{
p[++np]=k(t);
if (l<ls(t)) ranging(l, ls(t)-1, l(t));
if (r>ls(t)) ranging(0, r-ls(t)-1, r(t));
}
}
void getrange(int l, int r){nr=np=0; ranging(l-1, r-1, roof);}
void dfs(int t){if (l(t)) dfs(l(t)); dfn[++top]=t; if (r(t)) dfs(r(t));} //DFS序
void Recycle(node *t)  //回收节点
{
if (!t->sum) return;
if (t->l) Recycle(t->l);
if (t->r) Recycle(t->r);
delete(t);
}
void reBuild(int &t)
{
top=0; dfs(t);
rep(i, 1, top) Recycle(t(dfn[i]));
Build(1, top, t);
}

//=========================================================================================

bool Insert(int r, int k, int h, int &t)
{
if (!t)
{
t=++V;
s(t)=1, k(t)=k, l(t)=r(t)=0, t(t)=blank;
Add(0, maxl, k, t(t));
return h>log(V)/log(1/a);
}
bool flag;
if (r<=ls(t))
flag=Insert(r, k, h+1, l(t));
else flag=Insert(r-ls(t)-1, k, h+1, r(t));
s(t)=ls(t)+rs(t)+1; Add(0, maxl, k, t(t));
if (flag && (max(ls(t), rs(t)) > a*s(t))) {reBuild(t); return false;}
return flag;
}
int Change(int r, int k, int t)
{
if (ls(t)==r)
{
int v=k(t);
Del(0, maxl, k(t), t(t));
Add(0, maxl, k(t)=k, t(t));
return v;
}
int v;
if (r<ls(t)) v=Change(r, k, l(t));
else v=Change(r-ls(t)-1, k, r(t));
Del(0, maxl, v, t(t));
Add(0, maxl, k, t(t));
return v;
}
int Query(int l, int r, int rank)
{
rank--;
getrange(l, r);
int L=0, R=maxl;
while (L<R)
{
int mid=(L+R)>>1, sum=0;
rep(i, 1, nr) sum+=range[i]->l->sum;
rep(i, 1, np) sum+=(p[i]>=L && p[i]<=mid) ? 1 : 0;
if (rank<sum)
{rep(i, 1, nr) range[i]=range[i]->l; R=mid;}
else
{rank-=sum; rep(i, 1, nr) range[i]=range[i]->r; L=mid+1;}
}
return L;
}

//=========================================================================================

int n, m, w[maxn], last=0;
int main()
{
blank->l=blank->r=blank;
n=read(); rep(i, 1, n) w[i]=read();
l(0)=r(0)=s(0)=0;
rep(i, 1, n) dfn[i]=++V, k(V)=w[i];
Build(1, n, roof);
m=read();
while (m--)
{
char ch=getchar(); while (ch!='Q' && ch!='M' && ch!='I') ch=getchar();
if (ch=='Q')
{
int x=read()^last, y=read()^last, z=read()^last;
printf("%d\n", last=Query(x, y, z));
}
else if (ch=='I')
{
int x=read()^last, y=read()^last;
Insert(x-1, y, 0, roof);
}
else
{
int x=read()^last, y=read()^last;
Change(x-1, y, roof);
}
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: