前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >P1903 【模板】分块/带修改莫队(数颜色)

P1903 【模板】分块/带修改莫队(数颜色)

作者头像
attack
发布2018-04-12 14:04:20
6100
发布2018-04-12 14:04:20
举报

题目描述

墨墨购买了一套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

说明

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

来源:bzoj2120

本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

裸的带修改的莫队

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cstdlib>
  7 #include<ctime>
  8 using namespace std;
  9 const int MAXN=10001;
 10 static void read(int &n)
 11 {
 12     char c='+';int x=0;bool flag=0;
 13     while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
 14     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c-48);c=getchar();}
 15     flag==1?n=-x:n=x;
 16 }
 17 int n,m;
 18 int a[MAXN];
 19 struct CX
 20 {
 21     int l,r,id,tm;// tm上一次的更改操作 
 22 }cx[MAXN];
 23 int cxnum;
 24 struct GG
 25 {
 26     int pos,val,pre;
 27 }gg[MAXN];
 28 int ggnum;
 29 int head[MAXN];
 30 int where[MAXN];
 31 int base;
 32 int vis[MAXN];// 是否有更改操作 
 33 int color[MAXN];
 34 int ans=0;
 35 int out[MAXN];
 36 int comp(const CX &a,const CX &b)
 37 {
 38     if(where[a.l]==where[b.l])
 39         return a.r<b.r;
 40     else 
 41         return where[a.l]<where[b.l];
 42 }
 43 int calc(int x)
 44 {
 45     if(vis[x])
 46     {
 47         if(--color[a[x]]==0)
 48             ans--;
 49     }
 50     else 
 51     {
 52         if(++color[a[x]]==1)
 53             ans++;
 54     }    
 55     vis[x]=!vis[x];
 56 }
 57 void change(int p,int v)
 58 {
 59     if(vis[p])
 60     {
 61         calc(p);
 62         a[p]=v;
 63         calc(p);
 64     }
 65     else
 66     a[p]=v;
 67 }
 68 
 69 int main()
 70 {
 71     read(n);read(m);
 72     for(int i=1;i<=n;i++)
 73         read(a[i]),head[i]=a[i];
 74     base=sqrt(n);
 75     for(int i=1;i<=n;i++)
 76         where[i]=(i-1)/base+1;
 77     for(int i=1;i<=m;i++)
 78     {
 79         char c;
 80         int x,y;
 81         cin>>c;
 82         read(x);read(y);
 83         if(c=='Q')// 查询 
 84         {
 85             cxnum++;
 86             cx[cxnum].l=x;
 87             cx[cxnum].r=y;
 88             cx[cxnum].id=cxnum;
 89             cx[cxnum].tm=ggnum;
 90         }
 91         else
 92         {
 93             ggnum++;
 94             gg[ggnum].pos=x;
 95             gg[ggnum].val=y;
 96             gg[ggnum].pre=head[x];
 97             head[x]=y;
 98         }
 99     }
100     sort(cx+1,cx+cxnum+1,comp);
101     int l=1,r=0;
102     for(int i=1;i<=cxnum;i++)
103     {
104         for(int j=cx[i-1].tm+1;j<=cx[i].tm;j++)
105             change(gg[j].pos,gg[j].val);
106         for(int j=cx[i-1].tm;j>=cx[i].tm+1;j--)
107             change(gg[j].pos,gg[j].pre);// 此处是pre,不是val!!! 
108         for(;l<cx[i].l;l++)
109             calc(l);
110         for(;l>cx[i].l;l--)
111             calc(l-1);
112         for(;r<cx[i].r;r++)
113             calc(r+1);
114         for(;r>cx[i].r;r--)
115             calc(r);
116         out[cx[i].id]=ans;
117     }
118     for(int i=1;i<=cxnum;i++)
119         printf("%d\n",out[i]);
120     return 0;
121 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 输入输出格式
  • 输入输出样例
  • 说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档