【细节题 离线 树状数组】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

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

时间: 2024-08-09 00:55:53

【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇的相关文章

区间的关系的计数 HDU 4638 离线+树状数组

题目大意:给你n个人,每个人都有一个id,有m个询问,每次询问一个区间[l,r],问该区间内部有多少的id是连续的(单独的也算是一个) 思路:做了那么多离线+树状数组的题目,感觉这种东西就是一个模板了,23333,反正都是定义右区间的. 这题的关键难度就是如何定义id是连续的呢.我们每次往区间里面放一个数值以后都要add(pos, 1),就是把pos~n的所有的关系都+1.然后如果说在pos之前就出现id-1,就要add(pos[id-1], -1)(同理id+1也是这样),这样子表示从pos[

HDU 5156 - Harry and Christmas tree (dfs序+离线树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=5156 BC#25的C题. 题意是:给出一颗大小为n的树,以1为根,然后给出m次染色,每次将节点u加上一种颜色(一个节点可以有多个颜色). 最后查询树上每个节点对应子树上包含的不同颜色数量. 当时这场比赛没有做,回来看一下题目,没看标解就试着敲了一遍,于是解题思路从一开始就走上了不归路. 标解是O(n+m)的方法,主要思路是将问题转为:一次染色表示将u到根节点的路径都染上这种颜色. 但这样做需要去重,因为如果u

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

TOJ 4105 Lines Counting(离线树状数组)

4105.   Lines Counting Time Limit: 2.0 Seconds   Memory Limit: 150000K Total Runs: 152   Accepted Runs: 47 On the number axis, there are N lines. The two endpoints L and R of each line are integer. Give you M queries, each query contains two interval

POJ 3416 Crossing --离线+树状数组

题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少. 解法:离线树状数组.点不在坐标轴上,即点不共线使这题简单了不少,可以离散化点,也可以不离散化,因为x,y <= 500000,直接就可以搞.我这里是离散的,其实也没比直接搞快. 见两个树状数组,一个先把所有点都modify进去,一个等待以后加元素. 然后将查询和给出的点都按y坐标排序,然后离线对

BZOJ 1227 [SDOI2009] 虔诚的墓主人 离线+树状数组+离散化

鸣谢:140142耐心讲解缕清了我的思路 题意:由于调这道题调的头昏脑涨,所以题意自己搜吧,懒得说. 方法:离线+树状数组+离散化 解析:首先深表本蒟蒻对出题人的敬(bi)意(shi).这道题简直丧心病狂,看完题后大脑一片空白,整个人都不好了,刚开始的思路是什么呢?暴力思想枚举每个墓碑,然后计算每个墓碑的虔诚度,然后再来统计.不过看看数据范围呢?10^9*10^9的矩阵,最多才10^5个树,光枚举就已经超时了,所以肯定不行.(不过要是考试真没思路我就那么搞了- -!) 然后也想到来枚举墓碑,不过

CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)

转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有出现偶数次的数异或的值. 思路:容易想到,把区间内的所有的数都异或得到的是出现奇数次的数的值,然后再异或该区间内的所有出现过的数(每个数只统计一次),得到的ans了. 第一个问题:得到询问区间的

BZOJ 1878 [SDOI2009]HH的项链 离线+树状数组

题意: 给一个n个数的序列,m个询问,每次询问一个区间内不相同的数的个数. 方法: 离线+树状数组 解析: 看完题后的确有段时间没有头绪,想过线段树来搞,不过好像很麻烦,然后听他们说离线下来搞.再推了1节课差不多就明白了. 离线和在线差距的确很大. 如果离线的话,所有的区间是呈线性的.大体思路是什么呢?就是每个数,我们都可以预处理出他上一次出现是在什么位置.然后对于一个区间的询问[l,r],我们可以这么去想这个询问:l~r中的数的上一次出现的位置在l左边的数的个数. 这样就很好弄了,先把所有的区

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球到达某个节点上,如果x==wi,那么球停在这个节点上 .当然,这个点是叶子节点也会停止 . 如果x<wi,那么有1/2的概率走向左子树,有1/2的概率走向右子树 . 如果x>wi,那么有1/8的概率走向左子树,有7/8的概率走向右子树 . 问球经过v节点的概率 .(停在v节点也算) 解法: 在线的话每一个节点建一棵根节点到该节点的线段树,离线的话就先