会修修的莫队--BZOJ2120: 数颜色

$n leq 10000$的数列,$m leq 10000$个操作,一:单点修改;二:查区间不同数字个数。修改数$leq 1000$,数字$leq 1000000$。

我不会告诉您这是三种写法的双倍经验题!!

一般可以把查区间不同个数改成:$pre_i$表示$i$之前的一个与她相同的数在哪,然后变成查某个区间$pre_i$在某个范围内的数量。可以主席树,也可分块。修改暴力重构。

方法三:带修莫队。按L块为第一关键字、R块为第二关键字、时间为第三关键字对询问排序,这样时间指针的移动复杂度是块数量的平方乘修改数。

理论上块大小取$n^{frac{2}{3}}$是最好的,但是注意一下修改数只有1000。。于是求个导画个图象(用电脑)可得块大小280左右时最优。加了个离散化跑得飞起。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<queue>
 6 //#include<time.h>
 7 //#include<complex>
 8 #include<algorithm>
 9 #include<stdlib.h>
10 using namespace std;
11 
12 int n,m,lq,lc,tot;
13 #define maxn 10011
14 #define maxm 288
15 int a[maxn],bel[maxn];
16 struct Ques{int l,r,t,id;}q[maxn];
17 bool cmp(const Ques a,const Ques b) {return bel[a.l]==bel[b.l]?(bel[a.r]==bel[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;}
18 struct Modi{int x,a,b;}mo[maxn];
19 
20 int lisa[maxn<<1],li;
21 int ss; int cnt[maxn<<1],ans[maxn];
22 void modify(int p,int type) {cnt[a[p]]+=type; if (type>0) ss+=cnt[a[p]]==1; else ss-=cnt[a[p]]==0;}
23 void timemodify(int L,int R,int p,int v) {if (L<=p && p<=R) modify(p,-1); a[p]=v; if (L<=p && p<=R) modify(p,1);}
24 
25 int main()
26 {
27     scanf("%d%d",&n,&lq); m=280;
28     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1; tot=bel[n];
29     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisa[++li]=a[i];
30     char c; lc=0;
31     for (int i=1,j=0;i<=lq;i++)
32     {
33         while ((c=getchar())!='R' && c!='Q');
34         if (c=='Q')
35         {
36             j++; scanf("%d%d",&q[j].l,&q[j].r);
37             q[j].id=j; q[j].t=lc;
38         }
39         else
40         {
41             lc++; scanf("%d%d",&mo[lc].x,&mo[lc].b);
42             mo[lc].a=a[mo[lc].x]; a[mo[lc].x]=mo[lc].b; lisa[++li]=mo[lc].b;
43         }
44     }
45     lq-=lc;
46     sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1;
47     for (int i=1;i<=n;i++) a[i]=lower_bound(lisa+1,lisa+1+li,a[i])-lisa;
48     for (int i=1;i<=lc;i++) mo[i].a=lower_bound(lisa+1,lisa+1+li,mo[i].a)-lisa,
49     mo[i].b=lower_bound(lisa+1,lisa+1+li,mo[i].b)-lisa;
50     
51     sort(q+1,q+1+lq,cmp);
52     int L=1,R=0,T=lc; ss=0;
53     for (int i=1;i<=lq;i++)
54     {
55         while (T>q[i].t) timemodify(L,R,mo[T].x,mo[T].a),T--;
56         while (T<q[i].t) T++,timemodify(L,R,mo[T].x,mo[T].b);
57         while (L<q[i].l) modify(L,-1),L++;
58         while (L>q[i].l) modify(L-1,1),L--;
59         while (R<q[i].r) modify(R+1,1),R++;
60         while (R>q[i].r) modify(R,-1),R--;
61         ans[q[i].id]=ss;
62     }
63     for (int i=1;i<=lq;i++) printf("%d
",ans[i]);
64     return 0;
65 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8571918.html