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

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

板子题

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

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

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

#include <bits/stdc++.h>
#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;
}
/*

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
后缀自动机被广泛应用于OI竞赛中,特别是在字符串相关的问题中。它是一种高效的数据结构,能够有效地解决各种字符串匹配、模式匹配和计数等问题。 首先,后缀自动机可以用于解决最长公共子串和最长公共子序列等问题。对于给定的两个字符串,可以将其加入到后缀自动机中,并通过动态规划的方式求解最长公共子串或子序列的长度。 其次,后缀自动机还可以用于解决多次询问下的子串出现次数问题。通过构建全局后缀自动机,可以在O(n)的时间复杂度内预处理字符串,并在O(m)的时间复杂度内得出任意子串的出现次数,其中n为字符串长度,m为询问总数。 另外,后缀自动机还可以用于解决包含多模式匹配的问题。通过将模式串加入到后缀自动机中,并预处理自动机的fail指针,可以在O(n)的时间复杂度内找到所有模式串在文本中的出现位置。这在处理大规模的文本匹配问题时非常有用。 此外,后缀自动机还可以进行字符串的字典序统计。通过在构建自动机时记录每个节点的信息,可以在O(n)的时间复杂度内得到字符串的字典序第k小/大的子串。 总之,后缀自动机在OI竞赛中有着广泛的应用,能够解决各种字符串相关的问题。通过巧妙地构建自动机,并充分利用其性质,可以实现高效的字符串算法,为解决复杂的字符串问题提供了有力的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值