解题:洛谷1903 数颜色/维护队列

题面

大力分块艹过去了

直接分块+bitset,离散化后记录每块内每种颜色出现的次数,这样一次修改是$O(1)$的(不算离散化的话)。然而查询时因为要合并块,所以复杂度是整块长度之和这个级别的的(虽然有个bitset的$frac{1}{32}$),直接把块大小$siz$设成$sqrt(n)$做大概会比较慢。

为了提高效率,这里可以适当加大块的大小,这样块合并会变少而零散区间的统计会变多,在这个题效率会更高一点(我一开始弄了一个$n^{frac{3}{5}}$的块大小(块最大的时候大概是660)卡过去了,最慢的点跑了600+ms,后来又试了试然后还加了个“输出优化(不知道有没有用啊=。=)”,把块大小搞成$n^{frac{3}{4}}$跑的更快了些(块最大的时候大概是3400),就是上面说的300ms+)

 1 // luogu-judger-enable-o2
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cctype>
 5 #include<bitset>
 6 #include<cstring>
 7 #include<algorithm>
 8 using namespace std;
 9 const int N=50005,M=100005,Sq=20;
10 struct a
11 {
12     int typ;
13     int ll,rr;
14 }q[N];
15 int n,m,t1,t2,t3,t4,sqr,cnt,xnt,len;
16 int pts[Sq][2],app[Sq][M]; 
17 int a[N],blo[N],uni[2*N];
18 bitset<M> sta[Sq],qry; 
19 char rd[5];
20 inline int read()
21 {
22     int ret=0;
23     char ch=getchar();
24     while(!isdigit(ch))
25         ch=getchar();
26     while(isdigit(ch))
27         ret=(ret<<1)+(ret<<3)+(ch^48),ch=getchar();
28     return ret;
29 }
30 inline void write(int x)
31 {
32     if(x>9) write(x/10);
33     putchar(x%10+48);
34 }
35 int main()
36 {
37     register int i,j;
38     n=read(),m=read(),xnt=n;
39     sqr=pow(n,0.75),pts[cnt=1][0]=1;
40     for(i=1;i<=n;i++)
41     {
42         a[i]=read(),uni[i]=a[i];
43         blo[i]=(i-1)/sqr+1;
44         if(i%sqr==0)
45         {
46             pts[cnt++][1]=i;
47             pts[cnt][0]=i+1; 
48         }
49     }
50     pts[cnt][1]=n; 
51     for(i=1;i<=m;i++)
52     {
53         scanf("%s",rd),t1=read(),t2=read();
54         q[i].ll=t1,q[i].rr=t2,q[i].typ=(rd[0]=='R');
55         if(q[i].typ) uni[++xnt]=t2;
56     }
57     sort(uni+1,uni+1+xnt),len=unique(uni+1,uni+1+xnt)-uni-1;
58     for(i=1;i<=n;i++)
59     {
60         a[i]=lower_bound(uni+1,uni+1+len,a[i])-uni;
61         if(++app[blo[i]][a[i]]==1) sta[blo[i]][a[i]]=true;
62     }
63     for(i=1;i<=m;i++)
64     {
65         t1=q[i].ll,t2=q[i].rr;
66         if(q[i].typ)
67         {
68             int bel=blo[t1],newc=lower_bound(uni+1,uni+1+len,t2)-uni;
69             if(!(--app[bel][a[t1]])) sta[bel][a[t1]]=false;
70             if(++app[bel][newc]==1) sta[bel][newc]=true; a[t1]=newc;
71         }
72         else 
73         {
74             qry.reset(),t3=blo[t1],t4=blo[t2];
75             if(t3!=t4)
76             {
77                 for(j=t1;j<=pts[t3][1];j++) qry[a[j]]=true;
78                 for(j=pts[t4][0];j<=t2;j++) qry[a[j]]=true;
79                 for(j=t3+1;j<=t4-1;j++) qry|=sta[j];
80             }
81             else for(j=t1;j<=t2;j++) qry[a[j]]=true;
82             write((int)qry.count()),puts("");
83         }
84     }
85     return 0;
86 } 
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9960350.html