带修莫队板子
Posted wushengyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带修莫队板子相关的知识,希望对你有一定的参考价值。
https://www.luogu.org/problem/P1903
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
struct Query //查询
int l,r,t,id;
q[51000];
struct Modify// 回退
int p,col; //p代表修改的下标
mo[51000];
int n,m,cnt1,cnt2,len,s,l = 1,r,t;
int a[51000],c[1001000],ans[51000],tti[51000];
//tti是修改的次数,c代表颜色种类,ans存的答案,a存的原数组
char opt;
bool cmp(Query x,Query y)
if (x.l/len!=y.l/len) return x.l/len<y.l/len;
if (x.r/len!=y.r/len) return x.r/len<y.r/len;
return x.t<y.t; //按照时间排序
void add(int x)
c[x]++;
if(c[x]==1) s+=c[x];
void del(int x)
c[x]--;
if(c[x]==0) s--;
void replace(int x) //交换时间轴
int xx=mo[tti[t]].p; //xx为第tti[t]次的修改的位置
if (xx>=l&&xx<=r)
s-=!(--c[a[mo[tti[t]].p]]); //
s+=!(c[mo[tti[t]].col]++);
swap(a[mo[tti[t]].p],mo[tti[t]].col);
int main()
ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=m;i++)
cin>>opt;
if (opt==‘Q‘)
++cnt1;
cin>>q[cnt1].l>>q[cnt1].r;
q[cnt1].t=i;
q[cnt1].id=cnt1;
else
++cnt2;
cin>>mo[cnt2].p>>mo[cnt2].col;
tti[i]=cnt2; //存的修改的编号
len=pow(n,2.0/3); //分块
sort(q+1,q+cnt1+1,cmp);
for (int i=1;i<=cnt1;++i)
while (t<q[i].t) if(tti[++t]) replace(t);
while (t>q[i].t) if(tti[--t]) replace(t);
while (l>q[i].l) add(a[--l]);
while (l<q[i].l) del(a[l++]);
while (r>q[i].r) del(a[r--]);
while (r<q[i].r) add(a[++r]);
ans[q[i].id]=s;
for (int i=1;i<=cnt1;i++) cout<<ans[i]<<endl;
以上是关于带修莫队板子的主要内容,如果未能解决你的问题,请参考以下文章