[bzoj2120][数颜色] (暴力 or 分块)

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

 

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


2016.3.2新加数据两组by Nano_Ape

Solution

先上简单的暴力,可以水过

#include <stdio.h>
#include <string.h>
#define M 1000010

inline int Rin() {
    int x=0,c=getchar(),f=1;
    for(; c<48||c>57; c=getchar())
        if(c==45)f=-1;
    for(; c>47&&c<58; c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    return x*f; }

char c;
int g[M],n,m,a[M],top,x,y,i,mark[M],ans;

int main() {
    n=Rin(),m=Rin();
    for(i=1; i<=n; i++) {
        a[i]=Rin();
        if(!g[a[i]])
            g[a[i]]=++top;
        a[i]=g[a[i]]; }
    while(m--) {
        do c=getchar(); while(c!='Q'&&c!='R');
        x=Rin(),y=Rin();
        if(c=='Q') {
            for(i=x,ans=0; i<=y; i++)
                if(mark[a[i]]!=m)
                    mark[a[i]]=m,ans++;
            printf("%d\n",ans);
        }
        else {
            if(!g[y])g[y]=++top;
            a[x]=g[y];
        }
    }
    return 0;
}

 一下是莫队的做法

otz menci

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 10010
#define M 1000010
#define RG register
#define inline __inline__ __attribute__((always_inline))

inline void Rin(RG int &x) {
    x=0;RG int c=getchar(),f=1;
    for(; c<48||c>57; c=getchar())
        if(c==45)f=-1;
    for(; c>47&&c<58; c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    x*=f; }

int n,m,block_size,a[N],utop,qtop,ans[N],cnt[M];

struct Update {
    int pos,eld,now; }U[N];

struct Request{
    int tim,l,r,id;

    bool operator < (const Request &other)const {
        if(l/block_size == other.l/block_size) {
            if(r/block_size == other.r/block_size)
                return tim < other.tim;
            return r/block_size < other.r/block_size; }
        return l/block_size < other.l/block_size; } }Q[N];

inline void prepare() {
    static int nowlist[N];
    memcpy(nowlist,a,sizeof a);
    for(RG int i=1; i<=utop; i++) {
        U[i].eld=nowlist[U[i].pos];
        nowlist[U[i].pos]=U[i].now; } }

inline void extend(RG int &tmp,RG int pos,RG int dir) {
    if(dir == 1) {
        if(++cnt[a[pos]]==1)
            tmp++; }
    else
        if(--cnt[a[pos]]==0)
            tmp--; }

inline void modify(RG int &tmp,RG int T,RG int l,RG int r,RG int dir) {
    RG Update x=U[T];
    if(dir == 1) {
        a[x.pos]=x.now;
        if(x.pos >=l && x.pos <= r) {
            if(--cnt[x.eld]==0)tmp--;
            if(++cnt[x.now]==1)tmp++; } }
    else {
        if(x.pos >=l && x.pos <= r) {
            if(--cnt[x.now]==0)tmp--;
            if(++cnt[x.eld]==1)tmp++; }
        a[x.pos]=x.eld; } }

inline void block_solve() {
    for(RG int l=1,r=0,ans=0,T=0,i=1; i<=qtop; i++) {
        while(r < Q[i].r)extend(ans,++r,1);
        while(r > Q[i].r)extend(ans,r--,-1);

        while(l > Q[i].l)extend(ans,--l,1);
        while(l < Q[i].l)extend(ans,l++,-1);

        while(T < Q[i].tim)modify(ans,++T,l,r,1);
        while(T > Q[i].tim)modify(ans,T--,l,r,-1);
        :: ans[Q[i].id]=ans; } }

int main() {

    Rin(n),Rin(m);
    for(RG int i=1; i<=n; i++)
        Rin(a[i]);
    for(RG int i=1; i<=m; i++) {
        RG char c;
        do c=getchar(); while(c != 'Q'&&c != 'R');
        if(c == 'Q') {
            ++qtop;
            Rin(Q[qtop].l),Rin(Q[qtop].r);
            Q[qtop].id=qtop;
            Q[qtop].tim=utop; }
        else {
            ++utop;
            Rin(U[utop].pos),Rin(U[utop].now); } }

    prepare();
    block_size=floor(pow(n,2.0/3)+1);
    std::sort(Q+1,Q+1+qtop);
    block_solve();

    for(RG int i=1; i<=qtop;i++)
        printf("%d\n",ans[i]);
    return 0; }

 

posted @ 2017-01-16 09:20  keshuqi  阅读(373)  评论(0编辑  收藏  举报