AC日记——数颜色 bzoj 2120

2120

 

思路:

  带修改的莫队;

  对于离线排序询问的算法,如何修改呢?

  每个询问添加一个修改标记;

  表示当前询问在第几个修改之后;

  然后把修改标记作为第三关键字来排序;

  每次更新端点,先更新时间;

  块的大小为n的2/3次方;

 

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 100050

struct QueryType {
    int l,r,t,id;
};
struct QueryType qu[maxn];

struct ChangeType {
    int to,x,h;
};
struct ChangeType cha[maxn];

int n,m,size=440,tot,num,ai[maxn],bel[maxn],ti[maxn*10],ans[maxn];
int now;

bool if_[maxn];

inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

bool cmp(QueryType aa,QueryType bb)
{
    if(bel[aa.l]==bel[bb.l])
    {
        if(bel[aa.r]==bel[bb.r]) return aa.t<bb.t;
        else return aa.r<bb.r;
    }
    else return aa.l<bb.l;
}

inline void change(int x)
{
    if(if_[cha[x].to])
    {
        ti[ai[cha[x].to]]--;
        if(!ti[ai[cha[x].to]]) now--;
    }
    cha[x].h=ai[cha[x].to];
    ai[cha[x].to]=cha[x].x;
    if(if_[cha[x].to])
    {
        if(!ti[ai[cha[x].to]]) now++;
        ti[ai[cha[x].to]]++;
    }
}

inline void unchange(int x)
{
    if(if_[cha[x].to])
    {
        ti[ai[cha[x].to]]--;
        if(!ti[ai[cha[x].to]]) now--;
    }
    ai[cha[x].to]=cha[x].h;
    if(if_[cha[x].to])
    {
        if(!ti[ai[cha[x].to]]) now++;
        ti[ai[cha[x].to]]++;
    }
}

inline void updata(int to,int x)
{
    int pos=ti[ai[to]];
    ti[ai[to]]+=x;
    if(ti[ai[to]]==0&&pos==1) now--;
    if(ti[ai[to]]==1&&pos==0) now++;
    if(x==1) if_[to]=true;
    else if_[to]=false;
}

int main()
{
    in(n),in(m);char ch[4];int l,r,t;
    for(int i=1;i<=n;i++) in(ai[i]),bel[i]=(i-1)/size;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",ch);in(l),in(r);
        if(ch[0]=='Q') qu[++tot].l=l,qu[tot].r=r,qu[tot].t=num,qu[tot].id=tot;
        else cha[++num].to=l,cha[num].x=r;
    }
    sort(qu+1,qu+tot+1,cmp),l=1,r=0,t=0,now=0;
    for(int no=1;no<=tot;no++)
    {
        while(t<qu[no].t) change(++t);
        while(t>qu[no].t) unchange(t--);
        while(r<qu[no].r) updata(++r,1);
        while(r>qu[no].r) updata(r--,-1);
        while(l<qu[no].l) updata(l++,-1);
        while(l>qu[no].l) updata(--l,1);
        ans[qu[no].id]=now;
    }
    for(int i=1;i<=tot;i++) printf("%d\n",ans[i]);
    fclose(stdin),fclose(stdout);
    return 0;
}

 

posted @ 2017-04-25 16:21  IIIIIIIIIU  阅读(202)  评论(0编辑  收藏  举报