您的位置:首页 > 理论基础 > 数据结构算法

bzoj 2120 数颜色 树状数组套平衡树

2015-12-01 18:28 411 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2120

写了一整天树状数组套平衡树,结果看题解这是一道暴力就能水过的题T_T

然而最后跑起来还是蛮快的,这点我很欣慰!

最后还是说树套树,因为这道题是从第L支笔到第R支笔中共有多少种不同的颜色,第i支笔我们可以记录前一个与它颜色相同的笔last和后一个与它颜色相同的笔next,将last加入平衡树。

这样,询问L到R中不同的颜色的时候,查找L到R中多少支笔的last小于L,即为所求。

修改时要麻烦一些,首先删掉f[x]位置的last,之后将f[x]位置修改为颜色y,之后再将f[x]位置加入平衡树,大概意思还是看代码吧。

ps:build函数是将一个数加入平衡树,change函数是从平衡树中删除一个数

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define N 10010
#define M 1000010
#define inf 0x3f3f3f3f
#define ls a[k].l
#define rs a[k].r
#define lowbit(x) x&-x
using namespace std;
struct ss
{
int last,next,v;
};
ss f
;
struct node
{
int l,r,v,w,size,rnd;
};
node a[N*100];
int n,tot,tmp,size;
int root
;
int color[M];

void updata(int k)
{
a[k].size=a[ls].size+a[rs].size+a[k].w;
}

void lturn(int &k)
{
int t=a[k].r;
a[k].r=a[t].l,a[t].l=k;
a[t].size=a[k].size;
updata(k);
k=t;
}

void rturn(int &k)
{
int t=a[k].l;
a[k].l=a[t].r,a[t].r=k;
a[t].size=a[k].size;
updata(k);
k=t;
}

void insert(int &k,int x)
{
if(!k)
{
k=++size;
a[k].v=x,a[k].w=a[k].size=1,a[k].rnd=rand();
return ;
}
a[k].size++;
if(x==a[k].v)a[k].w++;
else if(x>a[k].v)
{
insert(a[k].r,x);
if(a[rs].rnd<a[k].rnd)lturn(k);
}else
{
insert(a[k].l,x);
if(a[ls].rnd<a[k].rnd)rturn(k);
}
}

void del(int &k,int x)
{
if(a[k].v==x)
{
if(a[k].w>1)a[k].w--,a[k].size--;
else if(a[k].l*a[k].r==0)k=a[k].l+a[k].r;
else if(a[ls].rnd<a[rs].rnd)rturn(k),del(k,x);
else lturn(k),del(k,x);
}
else if(x>a[k].v)del(a[k].r,x),a[k].size--;
else del(a[k].l,x),a[k].size--;
}

int query(int k,int x)
{
if(!k)return 0;
if(x<=a[k].v)return query(a[k].l,x);
else return a[k].w+a[ls].size+query(a[k].r,x);
}

void build(int x,int c)
{
for(int i=x;i<=n;i+=lowbit(i))
insert(root[i],c);
}

void change(int x,int c)
{
for(int i=x;i<=n;i+=lowbit(i))
del(root[i],c);
}

int ask(int x,int c)
{
int ans=0;
if(!x)return 0;
for(int i=x;i>0;i-=lowbit(i))
ans+=query(root[i],c);
return ans;
}

int main()
{
cin>>n>>tot;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
f[i].last=color[x],f[i].v=x;
f[color[x]].next=i,color[x]=i,f[i].next=inf;
build(i,f[i].last);
}
for(int i=1;i<=tot;i++)
{
char s[10];
int x,y;
scanf("%s%d%d",s,&x,&y);
if(s[0]=='Q')printf("%d\n",ask(y,x)-ask(x-1,x));
else{
change(x,f[x].last);
change(f[x].next,x);
build(f[x].next,f[x].last);
if(f[x].last!=0)f[f[x].last].next=f[x].next;
if(f[x].next!=inf)f[f[x].next].last=f[x].last;
if(f[x].next==inf)color[f[x].v]=f[x].last;
f[x].v=y,f[x].last=color[y],f[x].next=0;
while(f[x].last>x)
{
f[x].next=f[x].last;
f[x].last=f[f[x].last].last;
}
if(f[x].next==0)f[x].next=inf;
if(f[x].last!=0)f[f[x].last].next=x;
if(f[x].next!=inf)f[f[x].next].last=x;
if(f[x].next==inf)color[y]=x;
build(x,f[x].last);
build(f[x].next,x);
change(f[x].next,f[x].last);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息