Luogu4113 HEOI2012 采花 树状数组

传送门


发现这种重复只算一个的题目老是想不出来……

老套路,先对询问离线,按照右端点从小到大排序。然后我们考虑在右端点右移时新加入的那些位置的贡献,设$pre_i$表示与第$i$个位置相同数字的最后一个位置,那么将第$t$个数字放入的时候,$pre_t$就会产生$1$的贡献,而$pre_{pre_t}$的贡献因为$pre_t$的贡献而变成$0$,可以使用树状数组维护,每一次查询一段区间的贡献和即可。

 1 #include<bits/stdc++.h>
 2 //This code is written by Itst
 3 using namespace std;
 4 
 5 inline int read(){
 6     int a = 0;
 7     bool f = 0;
 8     char c = getchar();
 9     while(c != EOF && !isdigit(c)){
10         if(c == '-')
11             f = 1;
12         c = getchar();
13     }
14     while(c != EOF && isdigit(c)){
15         a = (a << 3) + (a << 1) + (c ^ '0');
16         c = getchar();
17     }
18     return f ? -a : a;
19 }
20 
21 const int MAXN = 2e6 + 7;
22 struct query{
23     int l , r , ind;
24 }que[MAXN];
25 int col[MAXN] , Tree[MAXN] , ans[MAXN] , last[MAXN][2] , N , c , Q;
26 
27 bool operator <(query a , query b){
28     return a.r < b.r;
29 }
30 
31 inline int lowbit(int x){
32     return x & -x;
33 }
34 
35 inline void modify(int x , int add){
36     while(x <= N){
37         Tree[x] += add;
38         x += lowbit(x);
39     }
40 }
41 
42 inline int get(int x){
43     int sum = 0;
44     while(x){
45         sum += Tree[x];
46         x -= lowbit(x);
47     }
48     return sum;
49 }
50 
51 inline void add(int x){
52     if(!last[col[x]][0])
53         last[col[x]][0] = x;
54     else{
55         if(last[col[x]][1])
56             modify(last[col[x]][1] , -1);
57         last[col[x]][1] = last[col[x]][0];
58         last[col[x]][0] = x;
59         modify(last[col[x]][1] , 1);
60     }
61 }
62 
63 int main(){
64 #ifndef ONLINE_JUDGE
65     freopen("4113.in" , "r" , stdin);
66     freopen("4113.out" , "w" , stdout);
67 #endif
68     N = read();
69     c = read();
70     Q = read();
71     for(int i = 1 ; i <= N ; ++i)
72         col[i] = read();
73     for(int i = 1 ; i <= Q ; ++i){
74         que[i].l = read();
75         que[i].r = read();
76         que[i].ind = i;
77     }
78     sort(que + 1 , que + Q + 1);
79     for(int i = 1 ; i <= Q ; ++i){
80         for(int j = que[i - 1].r + 1 ; j <= que[i].r ; ++j)
81             add(j);
82         ans[que[i].ind] = get(N) - get(que[i].l - 1);
83     }
84     for(int i = 1 ; i <= Q ; ++i)
85         printf("%d\n" , ans[i]);
86     return 0;
87 }

猜你喜欢

转载自www.cnblogs.com/Itst/p/10090573.html
今日推荐