P1903 [国家集训队]数颜色 / 维护队列(莫队区间询问+单点修改)
题目链接:https://www.luogu.org/problemnew/show/P1903
题目大意:中文题目
具体思路:莫队单点修改+区间询问模板题,在原来的区间询问的基础上,我们要记录当前这次操作之前单点修改的操作都有哪些,如果有多余的操作,就先消除这些操作:如果操作数还不够,就在加上这些操作就可以了,这个题会卡常数,注意block的赋值。
block的赋值 = ceil(exp((log(n)+log(num1))/3));这里的num1指的是操作数,n代表点的个数。
然后我们可以对比一下我写的这篇文章,
P1494 [国家集训队]小Z的袜子(莫队)
,在每一次指针的移动的时候,这个题需要把先前的影响给去掉,又因为每一次值的个数需要平方,所以需要先把原来的影响给去掉再去加上新的影响。而这个题我们是只需要判断当前的点是1还是0就可以了。
AC代码:
1 #include<iostream>
2 #include<cmath>
3 #include<stdio.h>
4 #include<algorithm>
5 #include<string>
6 #include<cstring>
7 using namespace std;
8 # define ll long long
9 const int maxn = 2e6+100;
10 int a[maxn],block;
11 struct node1
12 {
13 int l,r,pos,id,num;
14 bool friend operator < (node1 t1,node1 t2)
15 {
16 if(t1.l/block!=t2.l/block)return t1.l/block<t2.l/block;
17 if(t1.r/block!=t2.r/block)return t1.r/block<t2.r/block;
18 return t1.num<t2.num;
19 }
20 } q1[maxn];
21 struct node2
22 {
23 int pos,val;
24 } q2[maxn];
25 int tot,vis[maxn],ans[maxn];
26 void update(int id,int pos)
27 {
28 if(q2[pos].pos>=q1[id].l&&q2[pos].pos<=q1[id].r)
29 {
30 if(--vis[a[q2[pos].pos]]==0)
31 tot--;
32 if(++vis[q2[pos].val]==1)
33 tot++;
34 }
35 swap(a[q2[pos].pos],q2[pos].val);
36 }
37 inline int read()
38 {
39 char c=getchar();int x=0,f=1;
40 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
41 while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
42 return x*f;
43 }
44 void solve(int num1)
45 {
46 int num=0,l=1,r=0;
47 tot=0;
48 for(int i=1; i<=num1; i++)
49 {
50 while(l<q1[i].l)if(--vis[a[l++]]==0)tot--;
51 while(l>q1[i].l)if(++vis[a[--l]]==1)tot++;
52 while(r<q1[i].r)if(++vis[a[++r]]==1)tot++;
53 while(r>q1[i].r)if(--vis[a[r--]]==0)tot--;
54 while(num<q1[i].num){
55 num++;
56 update(i,num);
57 }
58 while(num>q1[i].num)
59 {
60 update(i,num);
61 num--;
62 }
63 ans[q1[i].id]=tot;
64 }
65 return ;
66 }
67 int main()
68 {
69 // cout<<pow(50000,5.0/3.0)<<endl;
70 // memset(vis,0,sizeof(vis));
71 // freopen("hqx.in","r",stdin);
72 int n,m;
73 n=read();
74 m=read();
75 //scanf("%d %d",&n,&m);
76 for(int i=1; i<=n; i++)
77 {
78 a[i]=read();
79 }
80 char str[10];
81 int st,ed;
82 int num1=0,num2=0;
83 while(m--)
84 {
85 scanf("%s",str);
86 st=read();
87 ed=read();
88 if(str[0]=='Q')
89 {
90 q1[++num1].l=st;
91 q1[num1].r=ed;
92 q1[num1].num=num2;
93 q1[num1].id=num1;
94 }
95 else if(str[0]=='R')
96 {
97 q2[++num2].pos=st;
98 q2[num2].val=ed;
99 }
100 }
101 block=ceil(exp((log(n)+log(num1))/3));
102 sort(q1+1,q1+num1+1);
103 solve(num1);
104 for(int i=1; i<=num1; i++)
105 {
106 printf("%d\n",ans[i]);
107 }
108 // for(int i=1;i<=5;i++){
109 // cout<<i<<" "<<vis[i]<<endl;
110 // }
111 return 0;
112 }