1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #define M 1000009
 6 using namespace std;
 7 int block,n,m,a[M],b[M],pre[M],pos[M],last[M],l[M],r[M],m1;
 8 int ask(int a1,int a2)
 9 {
10     int ans=0;
11     if(pos[a1]==pos[a2])
12       {
13         for(int i=a1;i<=a2;i++)
14           if(b[i]<a1)
15             ans++;
16       }
17     else
18       {
19         for(int i=a1;i<=r[pos[a1]];i++)
20           if(b[i]<a1)
21             ans++;
22         for(int i=l[pos[a2]];i<=a2;i++)
23           if(b[i]<a1)
24             ans++;
25         for(int i=pos[a1]+1;i<pos[a2];i++)
26           ans+=lower_bound(pre+l[i],pre+r[i]+1,a1)-pre-l[i];
27       }
28     return ans;  
29 }
30 void jian(int i)
31 {
32     l[i]=(i-1)*block+1;
33     r[i]=min(n,i*block);
34     for(int j=l[i];j<=r[i];j++)
35         pre[j]=b[j];
36     sort(pre+l[i],pre+r[i]+1);
37 }
38 void gai(int x,int y)
39 {
40     for(int i=1;i<=n;i++)
41       last[a[i]]=0;
42     a[x]=y;
43     for(int i=1;i<=n;i++)
44       {
45         int t=b[i];
46         b[i]=last[a[i]];
47         if(t!=last[a[i]])
48           jian(pos[i]);
49         last[a[i]]=i;
50       }
51 }
52 int main()
53 {
54     scanf("%d%d",&n,&m1);
55     for(int i=1;i<=n;i++)
56       scanf("%d",&a[i]);
57     block=(int)sqrt(n+log(2*n)/log(2));
58     m=n/block;
59     if(n%block)
60       m++;
61     for(int i=1;i<=n;i++)
62       {
63         b[i]=last[a[i]];
64         last[a[i]]=i;
65         pos[i]=(i-1)/block+1;
66       }
67     for(int i=1;i<=m;i++)
68       jian(i);
69     for(int i=1;i<=m1;i++)
70       {
71         char ch[5];
72         int a1,a2;
73         scanf("%s%d%d",ch,&a1,&a2);
74         if(ch[0]=='Q')
75           printf("%d\n",ask(a1,a2));
76         else
77           gai(a1,a2);
78       }
79     return 0;
80 }

暴力分块,每个点存下一个与他相同颜色的在哪,每个块内排序,找的时候首尾暴力判断每个点下一个颜色在不在区间外,不在就答案加加,中间二分。修改时重建每个点存的下一个点,

如果改了,就重建这个块。

posted on 2016-03-18 23:03  xiyuedong  阅读(151)  评论(0编辑  收藏  举报