【细节题 离线 树状数组】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\n",ans[i]); 82 return 0; 83 }
END