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

来源:互联网 发布:广州海度网络是培训吗 编辑:程序博客网 时间:2024/06/06 00:46

传送门: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&-xusing namespace std;struct ss{    int last,next,v;};ss f[N];struct node{    int l,r,v,w,size,rnd;};node a[N*100];int n,tot,tmp,size;int root[N];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;}
0 0
原创粉丝点击