P1903 [国家集训队]数颜色 / 维护队列(带修莫队)

P1903 [国家集训队]数颜色 / 维护队列

板子题

带修莫队的的和普通莫队的区别就在于增加了修改操作

在一操作,求完之后在看修改的,把修改的部分加上去,加到该次操作之前

另外这里的块大小应该设为 n 2 3 n^{\frac{2}{3}} n32才能过,一般的根号过不了

#include 
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=1e9+7;
const int M=1e9;
const int N=2e6+5;//?????????? 4e8
struct nc
{
	int l,r,pre,id;
}q[N];
struct node
{
	int pos,val;
}c[N];
int qnum,cnum,n,m,a[N],v[N];
int siz;
int ans,qes[N];
int cmp(nc i,nc j)
{
	if(i.l/siz!=j.l/siz)  return i.l/siz<j.l/siz;
	if(i.r/siz!=j.r/siz)  return i.r/siz<j.r/siz;
	return i.pre<j.pre;
}
void add(int x)
{
	if(++v[a[x]]==1)  ans++;
}
void del(int x)
{
	if(--v[a[x]]==0)  ans--;
}
void work(int now,int i)
{
	if(c[now].pos>=q[i].l&&c[now].pos<=q[i].r)
	{
		if(--v[a[c[now].pos]]==0)  ans--;
		if(++v[c[now].val]==1)  ans++;
	}
	swap(c[now].val,a[c[now].pos]);
}
void solve()
{
	int l=1,r=0,now=0;
	cin>>n>>m;
	siz=pow(n,2.0/3.0);
	for(re i=1;i<=n;i++)  scanf("%d",&a[i]);
	for(re i=1;i<=m;i++)
	{
		char op[10];
		int l,r;
		scanf("%s%d%d",op,&l,&r);
		if(op[0]=='Q')  q[++qnum]=(nc){l,r,cnum,qnum};
		else  c[++cnum]=(node){l,r};
	}
	sort(q+1,q+qnum+1,cmp);
	for(re i=1;i<=qnum;i++)
	{
		while(l<q[i].l)  del(l++);
		while(l>q[i].l)  add(--l);
		while(r<q[i].r)  add(++r);
		while(r>q[i].r)  del(r--);
		while(now<q[i].pre)  work(++now,i);
		while(now>q[i].pre)  work(now--,i);
		qes[q[i].id]=ans;
	}
	for(re i=1;i<=qnum;i++)  printf("%d\n",qes[i]);
}
signed main()
{
//	freopen("P1505_1.txt", "r", stdin);
//	freopen("Aout.txt", "w", stdout);
    int T=1;
//    cin>>T;
    for(int index=1;index<=T;index++)
    {
//        printf("Case #%lld: ",index);
        solve();
//        puts("");
    }
    return 0;
}
/*

*/

你可能感兴趣的:(高阶数据结构,数据结构)