数颜色(带修莫队模板)
Posted hsez-cyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数颜色(带修莫队模板)相关的知识,希望对你有一定的参考价值。
Description
题目描述
墨墨购买了一套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支画笔中共有几种不同颜色的画笔。
Solution
带修莫队模板(加一重排序元素:时间)
注意:每个时间点修改前 值可能不一样!!!卡了我一下午。。。
另外记得一定要吸氧
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; const int N=1e6+10; int n,m,T[N][3],a[N],nt,nl,nr,s[N],si,cnt,ans[N],an,tot; char ch[5]; struct node { int l,r,t,id; bool operator <(const node &o)const { return l/si==o.l/si?(r/si==o.r/si?t<o.t:r<o.r):l<o.l; } }q[N]; void get(int x,int d) { s[x]+=d; if(d<0) an-=s[x]==0; if(d>0) an+=s[x]==1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=0;i<m;i++) { scanf("%s",ch); if(ch[0]==‘Q‘) { scanf("%d%d",&q[tot].l,&q[tot].r); q[tot].t=cnt,q[tot].id=tot,tot++; } else { ++cnt,scanf("%d%d",&T[cnt][0],&T[cnt][2]); T[cnt][1]=a[T[cnt][0]]; a[T[cnt][0]]=T[cnt][2]; } } for(int i=cnt;i;i--) a[T[i][0]]=T[i][1]; si=ceil(exp((log(n)+log(cnt))/3)); sort(q,q+tot); for(int i=0;i<tot;i++) { while(q[i].l<nl) an+=!s[a[--nl]]++; while(q[i].l>nl) an-=!--s[a[nl++]]; while(q[i].r>nr) an+=!s[a[++nr]]++; while(q[i].r<nr) an-=!--s[a[nr--]]; while(q[i].t<nt) { int wz=T[nt][0]; if(nl<=wz && wz<=nr) an-=!--s[a[wz]]; a[wz]=T[nt--][1]; if(nl<=wz && wz<=nr) an+=!s[a[wz]]++; }; while(q[i].t>nt) { int wz=T[++nt][0]; if(nl<=wz && wz<=nr) an-=!--s[a[wz]]; a[wz]=T[nt][2]; if(nl<=wz && wz<=nr) an+=!s[a[wz]]++; }; ans[q[i].id]=an; } for(int i=0;i<tot;i++) printf("%d ",ans[i]); return 0; }
以上是关于数颜色(带修莫队模板)的主要内容,如果未能解决你的问题,请参考以下文章