[HZOI 2015]疯狂的颜色序列

%ad大神的脑洞,这题是强制在线版的HH的项链

所以可以考虑树套树,和主席树之类的做法

对于每个点,可以将这个点的颜色上一次出现的位置插入到主席树里,对于每一个 l ~ r 的询问, l 到 r 之间有多少颜色上一次出现的位置在0 到 l-1 内就是答案

 1 #define MAXN 500010UL
 2 #include <cstdio>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 int n, m, Rt[MAXN], num, ans, lt[MAXN];
 8 
 9 struct Seg {
10     int ls, rs, val;
11 }bn[MAXN*20];
12 
13 void Insert(int lrt, int &rt, int l, int r, int pos) {
14     rt = ++ num;
15     bn[rt] = bn[lrt];
16     if(l==r) {
17         ++ bn[rt].val;
18         return;
19     }
20     int mid = (l+r)>>1;
21     if(pos<=mid) Insert(bn[lrt].ls, bn[rt].ls, l, mid, pos);
22     else Insert(bn[lrt].rs, bn[rt].rs, mid+1, r, pos);
23     bn[rt].val = bn[bn[rt].ls].val+bn[bn[rt].rs].val;
24     return;
25 }
26 
27 void Find(int lrt, int rt, int l, int r, int ls, int rs) {
28     if(bn[rt].val-bn[lrt].val<=0) return;
29     if(ls<=l&&rs>=r) {
30         ans += bn[rt].val-bn[lrt].val;
31         return;
32     }
33     int mid = (l+r)>>1;
34     if(ls<=mid) Find(bn[lrt].ls, bn[rt].ls, l, mid, ls, rs);
35     if(rs>mid) Find(bn[lrt].rs, bn[rt].rs, mid+1, r, ls, rs);
36     return;
37 }
38 
39 void In(int &x) {
40     x = 0;
41     char tmp = getchar();
42     while(tmp<'0'||tmp>'9') tmp = getchar();
43     while(tmp>='0'&&tmp<='9') x = x*10+tmp-'0', tmp = getchar();
44     return;
45 }
46 
47 int main() {
48     freopen("color_seq.in", "r", stdin);
49     freopen("color_seq.out", "w", stdout);
50     In(n), In(m);
51     for(int i = 1, x ; i <= n ; ++ i) {
52         In(x);
53         Insert(Rt[i-1], Rt[i], 0, n, lt[x]);
54         lt[x] = i;
55     }
56     for(int i = 1, l, r ; i <= m ; ++ i) {
57         In(l), In(r);
58         l = (l+ans)%n+1, r = (r+ans)%n+1;
59         if(l>r) swap(l, r);
60         ans = 0, Find(Rt[l-1], Rt[r], 0, n, 0, l-1);
61         printf("%d\n", ans);
62     }
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/assassain/p/5441182.html