数颜色(洛谷-P1903)

题目描述

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

为了满足墨墨的要求,你知道你需要干什么了吗?

输入输出格式

输入格式:

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。

第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。

第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

输出格式:

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

输入输出样例

输入样例#1:

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

输出样例#1:

4
4
3
4

思路:带修莫队模版题

源代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-9
#define INF 0x3f3f3f3f
#define LL long long
const int MOD=10007;
const int N=1000000+5;
const int dx[]= {-1,1,0,0};
const int dy[]= {0,0,-1,1};
using namespace std;

struct Node{
    int l,r;//询问的左右端点
    int time;//时间维度
    int id;//询问的编号
}q[N];
struct Change{
    int pos;//要修改的位置
    int col;//要改成的值
}c[N];
int n,m,a[N];
int block;//分块
int numQ,numC;//查询、修改操作的次数
LL ans,cnt[N];
LL res[N];

bool cmp(Node a,Node b){//排序
    return (a.l/block)^(b.l/block) ? a.l<b.l : ((a.r/block)^(b.r/block)?a.r<b.r:a.time<b.time);
}

void add(int x){//统计新的,根据具体情况修改
    if(cnt[x]==0)
        ans++;
    cnt[x]++;

}
void del(int x){//减去旧的,根据具体情况修改
    cnt[x]--;
    if(cnt[x]==0)
        ans--;
}
void change(int x,int ti){//改变时间轴
    if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r){
        del(a[c[ti].pos]);//删除指定位置上的值
        add(c[ti].col);//统计新的数
    }
    swap(c[ti].col,a[c[ti].pos]);//直接互换,下次执行时必定是回退这次操作
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        ans=0;
        numQ=0;
        numC=0;
        memset(cnt,0,sizeof(cnt));
        block=pow(n,0.66666);//分块

        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);

        for(int i=1;i<=m;i++){
            char op[10];
            scanf("%s",op);
            if(op[0]=='Q'){//查询操作
                ++numQ;//查询操作次数+1
                scanf("%d%d",&q[numQ].l,&q[numQ].r);
                q[numQ].id=numQ;//序号
                q[numQ].time=numC;//时间轴
            }
            else{//修改操作
                ++numC;//修改操作次数+1
                scanf("%d%d",&c[numC].pos,&c[numC].col);
            }
        }
        sort(q+1,q+numQ+1,cmp);//对询问进行排序
        int l=1,r=0,time=0;//左右指针与时间轴
        for(int i=1;i<=numQ;i++){
            int ql=q[i].l,qr=q[i].r;//询问的左右端点
            int qtime=q[i].time;//询问的时间轴
            while(l>ql) add(a[--l]);//[l-1,r,time]
            while(l<ql) del(a[l++]);//[l+1,r,time]
            while(r<qr) add(a[++r]);//[l,r+1,time]
            while(r>qr) del(a[r--]);//[l,r-1,time]
            while(time<qtime) change(i,++time);//[l,r,time+1]
            while(time>qtime) change(i,time--);//[l,r,time-1]
            res[q[i].id]=ans;//获取答案
        }

        for(int i=1;i<=numQ;i++)
            printf("%lld\n",res[i]);
    }
    return 0;
}
发布了1871 篇原创文章 · 获赞 702 · 访问量 194万+

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/88317597
今日推荐