【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇

歧义差评;但是和题意理解一样了之后细节依然处理了很久,说明还是水平不够……

题目描述

Marisa来到了森林之中,看到了一排nn个五颜六色的蘑菇,编号从1-n1−n,这些蘑菇的颜色分别为col[1],col[2]...col[n]col[1],col[2]...col[n]由于她很挑剔,所以她只会采那些"魔法蘑菇"

一个蘑菇被叫做"魔法蘑菇",当且仅当它在给定的某段区间内,并且在这段给定区间内与它颜色相同的蘑菇(包括它本身)的个数 与在这个给定区间外这种颜色的蘑菇的个数之差小于等于常数kk

现在Marisa会做出mm个询问,每次询问你[l,r][l,r]中有多少种不同颜色的"魔法蘑菇"

输入输出格式

输入格式:

第一行三个整数n,m,kn,m,k
第二行nn个正整数,表示蘑菇的颜色col[i]col[i]
之后mm行,每行两个正整数l,rl,r,表示Marisa询问的区间的左端点和右端点,数据保证0<l≤r≤n0<l≤r≤n

输出格式:

共mm行,每行一个整数xx,表示询问区间中不同颜色的"魔法蘑菇"的数量


题目分析

这是一类经典的区间问题。形如mex和HH的项链。 

区别在于对于每一个点来说,合法区间是$l[i],r[i]$————那么就是预处理的细节要多加小心。其他操作都是大同小异的。

 1 #include<bits/stdc++.h>
 2 const int maxn = 2000035;
 3 
 4 struct QRs
 5 {
 6     int l,r,id;
 7     bool operator < (QRs a) const
 8     {
 9         return l < a.l;
10     }
11 }q[maxn];
12 int n,m,k,now;
13 std::vector<int> w[maxn];
14 int a[maxn],t[maxn],f[maxn],v[maxn];
15 int st[maxn],pre[maxn],nxt[maxn],ans[maxn];
16 
17 int read()
18 {
19     char ch = getchar();
20     int num = 0;
21     bool fl = 0;
22     for (; !isdigit(ch); ch=getchar())
23         if (ch=='-') fl = 1;
24     for (; isdigit(ch); ch=getchar())
25         num = (num<<1)+(num<<3)+ch-48;
26     if (fl) num = -num;
27     return num;
28 }
29 int lowbit(int x){return x&-x;}
30 void add(int x, int c)
31 {
32     if (!x) return;
33     for (; x<=n; x+=lowbit(x)) f[x] += c;
34 }
35 int query(int x)
36 {
37     int ret = 0;
38     for (; x; x-=lowbit(x)) ret += f[x];
39     return ret;
40 }
41 void update(int x, int c)
42 {
43     add(st[x], c), add(nxt[x], -c);
44 }
45 int main()
46 {
47     n = read(), m = read(), k = read();
48     for (int i=1; i<=n; i++)
49         a[i] = read(), v[i] = ++t[a[i]], w[a[i]].push_back(i);
50     for (int i=1; i<=n; i++)
51     {
52         int lft = (t[a[i]]+k)/2, rgt = (t[a[i]]-k+1)/2;
53         if (v[i]+lft-1 < t[a[i]]){
54             if (v[i]+lft-1 >= 0) nxt[i] = w[a[i]][v[i]+lft-1];
55             else nxt[i] = i;
56         }
57         else nxt[i] = n+1;
58         if (rgt >= 1&&v[i]+rgt-2 >= 0){
59             if (v[i]+rgt-2 < t[a[i]]) st[i] = w[a[i]][v[i]+rgt-2];
60             else st[i] = n+1;
61         }
62         else st[i] = i;
63         if (v[i] < t[a[i]])
64             pre[i] = w[a[i]][v[i]];
65         else pre[i] = n+1;
66     }
67     for (int i=1; i<=n; i++)
68         if (t[a[i]]){
69             update(i, 1);
70             t[a[i]] = 0;
71         }
72     for (int i=1; i<=m; i++)
73         q[i].l = read(), q[i].r = read(), q[i].id = i;
74     std::sort(q+1, q+m+1);
75     for (int i=1; i<=m; i++)
76     {
77         for (; now < q[i].l; now++)
78             update(now, -1), update(pre[now], 1);
79         ans[q[i].id] = query(q[i].r)-query(q[i].l-1);
80     }
81     for (int i=1; i<=m; i++) printf("%d
",ans[i]);
82     return 0;
83 }

END

原文地址:https://www.cnblogs.com/antiquality/p/9769428.html