(火神:爷究竟交了些什么冤种……)
原题目链接:link
「他的好朋友风神给他一个有 N 个自然数的数组,然后对他进行 Q 次查询。每一次查询包含两个正整数 \(L,R\),表示一个数组中的一个区间 \([L,R]\),火神需要回答在这个区间中有多少个值刚好出现 \(2\) 次」,对于这种单点修改区间查询(但此处是对区间元素种类总数的查询),自然是想到树状数组,当然也有可能是莫队。(对于目前所学而言,题型:树状数组)
先从最简单的想起。假如数组元素全部相同的话(默认枚举指针为 \(i\))。
(就像酱紫↓)

随着区域左指针不变,右指针从左往右遍历,我们应该如何去维护呢。

当区域为 \([1,1]\) 时,没有值刚好出现 \(2\) 次的元素。恰好,我们什么都不需要操作。

当区域为 \([1,2]\) 时,\(i\) 号元素 \(3\) 与 \(i - 1\) 号元素相同,\(i - 1\) 号元素的位置上加一(表示该位与该位的后一个数相同)。在这一个区间里,\(3\) 刚好出现 \(2\) 次,所以区域 \([1,2]\) 的价值为 \(1\) ,维护成功。

当区域为 \([1,3]\) 时,\(i\) 号元素 \(3\) 与 \(i - 1\) 号元素相同,\(i - 1\) 号元素的位置上加一。在这一个区间里,\(3\) 出现 \(3\) 次,没有刚好出现两次的值,所以区域 \([1,3]\) 的价值应该为 \(0\),但此时却是 \(2\)。

于是,我们在当前 \(i - 2\) 号元素的位置上减 \(2\)(表示该元素后面还有两个相邻元素与它相同。\(3\) 个连续元素相同,其价值为零)。此时区域 \([1,3]\) 的价值为 \(0\),维护成功。

当区域为 \([1,4]\) 时,\(i\) 号元素 \(3\) 与 \(i - 1\) 号元素相同,\(i - 1\) 号元素的位置上加一。在这一个区间里,\(3\) 出现 \(4\) 次,没有刚好出现两次的值,所以区域 \([1,4]\) 的价值应该为 \(0\),但此时却是 \(-1\)。

于是,我们在当前 \(i - 3\) 号元素的位置上加 \(1\)(表示该元素后面有三个连续元素与它相同,加一来维护平衡。\(4\) 个连续元素相同,其价值仍为零)。此时区域 \([1,4]\) 的价值为 \(0\),维护成功。

当区域为 \([1,5]\) 时,\(i\) 号元素 \(3\) 与 \(i - 1\) 号元素相同,\(i - 1\) 号元素的位置上加一,在 \(i - 2\) 号元素的位置上减 \(2\),在 \(i - 3\) 号元素的位置上加 \(1\)。可以发现,此时我们维护成功了。以此类推,后面所有操作都是平衡的。(蓝色的加一表示:该位与后一位数相同; 绿色的减二表示:该元素后面还有两个相邻元素与它相同,减去多算的两对;紫色的加一表示:该元素后面有三个连续元素与它相同,补上多去的一对)
看完后你可能会发出疑问,你是不是「dou」得呀???欸,还真不是。

我们在计算的时候总是在 \(i - 1\) 号位上加一,是为了记录当前有多少对满足题意的元素(在图中等价于记录当前位置的左括号有多少,其前缀和即当前区间 \([1,i]\) 满足题意的元素对数)。但是遇到上图这种情况,(连续三个元素相等,出现两对相同元素)我们需要舍弃这两对,于是乎在 \(i - 2\) 号位上减二。你可能又会问,那为啥不在 \(i - 1\) 号位上减呢?那如果在 \(i - 1\) 号位上减的话,区间 \([i - 1, i]\) 你又打算怎么算呢。

遇到这种情况时,我们的操作是在\(i - 1\) 号元素的位置上加一,在 \(i - 2\) 号元素的位置上减 \(2\),在 \(i - 3\) 号元素的位置上加 \(1\)。前面两个操作已解释过,不再赘述。如图(四个相同元素同框),我们按前两个操作记录了满足题意的对数,舍弃不符合题意的,这时候,我们会发现——我们实际舍弃了四对(\(i - 2\) 号减二,\(i - 3\) 号减二),实际只需舍弃三对。于是乎,在 \(i - 3\) 号位上加一,表示我多舍弃了一对,现补上(如果你要问为什么不在其他位加一,我只能告诉你是为了后面方便求答案,道理同前)。
前面光是讲全是相同元素的情况了,可实际的数据不一定是这样啊 (疑似伪证)。别急,我们将这种观念放进数据,思考:是否可以将原数据改造成我们想要的样子呢?
(搞笑哦)
确实可以。我们可以将相同的元素分别穿在同一条链上,分别计算。明显的,我们这样互不干扰的计算没有问题,只需同类与同类进行比较,将答案累加即可(在实现中,累加等价于直接在同一个树状数组中)。
特别的,我们需要边维护边出答案。如果维护完了再出答案的话,部分靠前的元素会记录到一些该区间本没有的信息。譬如 \(3\ 3\ 3\ 3\ 3\ 3\ 3\ 3\),若是维护完后再求区间 \([1,3]\) 的话,\(2\) 号位会记录到信息:「该元素后面还有两个相邻元素与它相同」,但实际该区间内并不存在这种情况。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 + 5;
int n, q, l, r, BIT[N], last[N], ans[N];
ll a[N];
map<ll, int> mp;
struct node {
int l, r, id;
} b[N];
bool cmp(node x, node y) { return x.r < y.r; }
int lowbit(int x) { return x & -x; }
void update(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
BIT[i] += k;
}
return;
}
int sum(int x) {
int ans = 0;
for (int i = x; i >= 1; i -= lowbit(i)) {
ans += BIT[i];
}
return ans;
}
int main() {
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf("%lld", a + i);
if (mp.find(a[i]) != mp.end()) {
last[i] = mp[a[i]];
} else {
last[i] = -1;
}
mp[a[i]] = i;
}
for (int i = 1; i <= q; i++) {
scanf("%d %d", &b[i].l, &b[i].r);
b[i].id = i;
}
sort(b + 1, b + q + 1, cmp);
int now = 1;
for (int i = 1; i <= q; i++) {
while (now <= b[i].r) {
if (last[now] != -1) {
update(last[now], 1);
if (last[last[now]] != -1) {
update(last[last[now]], -2);
if (last[last[last[now]]] != -1) {
update(last[last[last[now]]], 1);
}
}
}
now++;
}
ans[b[i].id] = sum(b[i].r) - sum(b[i].l - 1);
}
for (int i = 1; i <= q; i++) {
printf("%d\n", ans[i]);
}
return 0;
}
赫菲斯托斯:阿涅弥伊你完犊子了!!1( 风神留下了 Accepted 扬长而去)
让我们来解决 『火神之友』 叭~
Bye bye!!1 ??
这是一道简单题题目来自:https://leetcode.cn/problems/two-sum/题目给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。提示:22nums.length104−109−109nums[i]109−109−109target109只会存在一个有效答案进阶:你可以想出一个时间复杂度小于O(n2)O(n^2)O(n2)的算法吗?示例1:输入:nums=[2,7,11,15],targe
没有测评,不知道对不对,仅仅过样例而已试题A:日期统计本题总分:5分【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素从左至右如下所示:5686916124919823647759503875815861830379270588570991944686338516346707827689565614010094809128502533现在他想要从这个数组中寻找一些满足以下条件的子序列: 1.子序列的长度为8; 2.这个子序列可以按照下标顺序组成一个yyyymmdd格式的日期,并且要求这个日期是2023年中的某一天的日期,例如202309
2023蓝桥C/C++B组省赛文章目录2023蓝桥C/C++B组省赛试题A:日期统计题目描述枚举参考代码试题B:01串的熵题目描述枚举|模拟参考代码试题C:冶炼金属题意描述取交集参考代码试题D:飞机降落题意描述DFS+剪枝,懒得写试题E:接龙数列题意描述DP参考代码试题F:岛屿个数题意描述dfs|连通块参考代码试题G:子串简写题意描述前缀和参考代码试题H:整数删除题意描述双向链表|最小堆参考代码试题I:景区导游题意描述带权LCA参考代码试题J:砍树题意描述树上差分参考代码试题A:日期统计题目描述【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素
83.删除排序链表中的重复元素题目描述给定一个已排序的链表的头head,删除所有重复的元素,使每个元素只出现一次。返回已排序的链表。输入:head=[1,1,2]输出:[1,2]解题思路:用一个指向节点类型的指针保存头结点,用另一个指向节点类型的指针对该链表进行遍历,由于是有序的,当出现不同的值就说明不会再出现跟前面的值相同的节点了,最后循环结束的条件是遍历到最后一个节点的时候,也就是该节点的next指向空的时候,停止循环,返回该保存的头结点,另外,如果传过来的头结点是空,则直接返回空。参考代码:/***Definitionforsingly-linkedlist.*structListNod
P1776宝物筛选宝物筛选题目描述终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物。这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了。小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为WWW的采集车,洞穴里总共有nnn种宝物,每种宝物的价值为viv_ivi,重量为wiw_iwi,每种宝物有mim_imi件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。输入
写在前面以下代码,目前均可通过民间OJ数据(dotcpp&NewOnlineJudge),两个OJ题目互补,能构成全集,可以到对应链接下搜题提交(感谢OJ对题目的支持)如果发现任何问题,包含但不限于算法思路出错、OJ数据弱算法实际超时、存在没考虑到的边界情况等,请及时联系作者题解A.幸运数(模拟)题面题解 由于是填空题,按题意本地暴力,几秒就跑出来结果了,直接交结果代码#includeusingnamespacestd;intans;intmain(){ /* for(inti=1;iB.有奖问答(搜索/dp)题面题解1.搜索:2的30次方种可能,每次要么+10要么清零,遇到100分时
最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理已参加机试人员的实战技巧文章目录最近更新的博客使用说明箱子之形摆放题目输入输出示例一输入输出说明备注Code
华为机试一共三道题,分值分别是100,100,200,满分400分,限时2.5小时。我抽到的这三题相对来说比较简单,满分通过,这里做个总结:第一题:数据分类■ 题目描述 对一个数据a进行分类,分类方法为:此数据a(四个字节大小)的四个字节相加对一个给定的值b取模,如果得到的结果小于一个给定的值c,则数据a为有效类型,其类型为取模的值;如果得到的结果大于或者等于c,则数据a为无效类型。比如一个数据a=0x01010101,b=3,按照分类方法计算(0x01+0x01+0x01+0x01)%3=1,所以如果c=2,则此a为有效类型,其类型为1,如果c=1,则此a为无效类型;又如一个数据a=0x01
只做出来(ACDFGH),挑几个出来,答案不一定正确,但自己测试通过了A、求和求1~20230408的和publicclassMain{ publicstaticvoidmain(String[]args){System.out.println((long)20230409*10115204); }}这里就直接套等差数列的求和公式,答案:204634714038436 D、平均【问题描述】 有一个长度为n的数组(n是10的倍数),每个数Ai都是区间[0,9]中的整数,小明发现数组里每种数出现的次数不太平均,而更改第i个数的代价为bi,他想更改着若干个数的值使得这10种数出现的次数
前言:Hello各位童学大家好!😊😊,茫茫题海你我相遇即是缘分呐,或许日复一日的刷题以及让你疲惫甚至已经厌倦了,但是我们真的真的达到极限了吗?少一点自我感动,没有结果前别太松懈,请相信”一万小时定理“。当你迷茫时抬头看看远方回想当初那个稚嫩脸庞的少年所仰望的目标😇😇,理想主义终需在现实里才能真正实现,接下来让我们静下心来刷题吧,体验学习的快感!🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🚀🏆题目传送门⭐L1-028判断素数(10分)⭐L1-031到底是不是太胖了(10分)⭐L1-025正整数A+B(15分)⭐L1-030一帮一(15分)⭐L1-027出租(20分)⭐L1-032Left-p