Dynamic len(set(a[L:R])) UVA - 12345

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3767

动态查询区间内有多少不同颜色

用set维护每种颜色出现的位置 set每次插入或擦除后仍满足单调性

对于[l,r]区间内有多少不同颜色 就看有多少位置i 其上颜色clr[i]之前出现的位置小于l 这样就讲问题转换为区间加和问题了 主要是修改操作时要照顾前后造成的影响比较麻烦

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int l;
    int r;
    int val;
};

set <int> st[1000010];
node tree[20000010];
int clr[50010],root[50010],groot[50010];
int n,q,num;

int lowbit(int x)
{
    return x&(-x);
}

int build(int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
    if(l==r) return cur;
    m=(l+r)/2;
    tree[cur].l=build(l,m);
    tree[cur].r=build(m+1,r);
    return cur;
}

int updateII(int rot,int tar,int val,int l,int r)
{
    int cur,m;
    cur=num++;
    tree[cur]=tree[rot];
    tree[cur].val+=val;
    if(l==r) return cur;
    m=(l+r)/2;
    if(tar<=m) tree[cur].l=updateII(tree[rot].l,tar,val,l,m);
    else tree[cur].r=updateII(tree[rot].r,tar,val,m+1,r);
    return cur;
}

void updateI(int bg,int tar,int val)
{
    int i;
    for(i=bg;i<=n;i+=lowbit(i))
    {
        groot[i]=updateII(groot[i],tar,val,0,n);
    }
}


int queryII(int rot,int pl,int pr,int l,int r)
{
    int res,m;
    if(pl<=l&&r<=pr)
    {
        return tree[rot].val;
    }
    res=0,m=(l+r)/2;
    if(pl<=m) res+=queryII(tree[rot].l,pl,pr,l,m);
    if(pr>m) res+=queryII(tree[rot].r,pl,pr,m+1,r);
    return res;
}

int queryI(int bg,int ed,int pl,int pr)
{
    int res,i;
    res=queryII(root[ed],pl,pr,0,n)-queryII(root[bg],pl,pr,0,n);
    for(i=bg;i>=1;i-=lowbit(i)) res-=queryII(groot[i],pl,pr,0,n);
    for(i=ed;i>=1;i-=lowbit(i)) res+=queryII(groot[i],pl,pr,0,n);
    return res;
}

int main()
{
    set <int> ::iterator it;
    int i,p1,p2,l,r,m;
    char op[10];
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&clr[i]);
        st[clr[i]].insert(i);
    }
    num=0;
    root[0]=build(0,n);
    for(i=1;i<=n;i++)
    {
        it=st[clr[i]].lower_bound(i);
        if(it==st[clr[i]].begin()) p1=0;
        else p1=*(--it);
        root[i]=updateII(root[i-1],p1,1,0,n);
    }
    for(i=1;i<=n;i++) groot[i]=root[0];
    while(q--)
    {
        scanf("%s%d%d",op,&l,&r);
        l++;
        if(op[0]=='M')
        {
            if(clr[l]==r) continue;
            it=st[clr[l]].lower_bound(l);
            if(it==st[clr[l]].begin()) p1=0;
            else
            {
                it--;
                p1=*it;
                it++;
            }
            it++;
            if(it==st[clr[l]].end()) p2=-1;
            else p2=*it;
            it--;
            st[clr[l]].erase(l);
            updateI(l,p1,-1);
            if(p2!=-1)
            {
                updateI(p2,l,-1);
                updateI(p2,p1,1);
            }

            it=st[r].upper_bound(l);
            if(it==st[r].begin()) p1=0;
            else
            {
                it--;
                p1=*it;
                it++;
            }
            if(it==st[r].end()) p2=-1;
            else p2=*it;
            st[r].insert(l);
            updateI(l,p1,1);
            if(p2!=-1)
            {
                updateI(p2,l,1);
                updateI(p2,p1,-1);
            }

            clr[l]=r;
        }
        else
        {
            printf("%d\n",queryI(l-1,r,0,l-1));
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81257416