1. 程式人生 > >Luogu4113 HEOI2012 採花 樹狀陣列

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 }