【题解】CF2009G1

devtools/2024/9/19 22:48:04/ 标签: 算法, c++

前言

  只会做G1 ,但尽量做到最好,除了一开始的排序的O(nlogn),后续处理都是O(n)。可能会对G2和G3有一点点用处。

翻译

原题链接CF2009G1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

  直接处理等差数列不方便,但这个等差数列性质特殊,即公差为1。所以在一个等差数列中, a [ i ] − i a[i]-i a[i]i就成了常数列。为了避免出现负数,我们将 a [ i ] a[i] a[i]更改为 a [ i ] + n − i a[i]+n-i a[i]+ni,然后问题转化为将这个长度为 k k k的数列转变为常数列的最小操作次数,易知等价于 k − k- k众数 的数量。

  我们使用滑动窗口,维护所有数量,数量的降序映射数组,和降序数组中数量相同的区间的左右边界。各种映射非常复杂,调了好久,下面举个例子:

  现在数组为 1 , 1 , 2 , 2 , 1 , 4 , 2 1,1,2,2,1,4,2 1,1,2,2,1,4,2
  数量数组为 3 , 3 , 0 , 1 3,3,0,1 3,3,0,1
  降序数组为 1 , 2 , 4 , 3 1,2,4,3 1,2,4,3
  边界为: [ 1 , 2 ] , [ 3 , 3 ] , [ 4 , 4 ] [1,2], [3,3],[4,4] [1,2],[3,3],[4,4]

  要维护这么多东西的目的就是让窗口滑动时,新增数据和删除数据的维护代价为O(1)。这是因为每次改变时,一个值对应的数量只会 + 1 +1 +1 − 1 -1 1。假如数量由 3 3 3变成了 4 4 4,那么交换自己和 3 3 3的左边界,然后调整一下 3 3 3 4 4 4的边界即可。

  最后,每次的答案就是数量数组第一个中对应的值。

代码

  尽量注释了,真太难说清楚了。把我注释的调试代码复原更好理解。

#include<bits/stdc++.h>
#define N 200005
#define int long long
using namespace std;
int n, k, q, a[N];
// cnt[值] =  值的数量 
// id[i] = cnt中数量第i多的值 
// re_id[值] = 这个值是第几多的 
// l[数量], r[数量] = 同样数量在id中的边界 
int cnt[2*N], id[2*N], re_id[2*N], ans[N];
int l[2*N], r[2*N];   // 每一种数量在id中的左右边界 
bool cmp(int x, int y) {return cnt[x] > cnt[y];
}
signed main() {int t; cin>>t;while(t--) {cin>>n>>k>>q;for(int i=0;i<=2*n;i++) {cnt[i] = 0;id[i] = i;}for(int i=1;i<=n;i++) {cin>>a[i];a[i] = a[i] + n - i;}
//		cout<<"a: "; for(int j=1;j<=n;j++) cout<<a[j]<<' '; cout<<endl;for(int i=1;i<=k;i++) {     // 初始化数量数组 cnt[a[i]]++;}sort(id+1, id+2*n+1, cmp);  // 初始化有序化数组id for(int i=0;i<=2*n;i++) re_id[id[i]] = i;   // 初始化re_id ans[k] = cnt[id[1]];for(int i=0;i<=2*n;i++) l[i] = r[i] = -1;   // 初始化l, r for(int i=1;i<=2*n;i++) {    // 初始化边界维护数组 if(cnt[id[i]] != cnt[id[i-1]]) {l[cnt[id[i]]] = i;r[cnt[id[i]]] = i;} else {r[cnt[id[i]]] = i;}} for(int i=k+1;i<=n;i++) {
//			cout<<endl;
//			cout<<"a_now: "; for(int j=i-k;j<=i-1;j++) cout<<a[j]<<' '; cout<<endl;
//			cout<<"cnt: "; for(int j=1;j<=2*n;j++) cout<<cnt[j]<<' '; cout<<endl;
//			cout<<"id: "; for(int j=1;j<=2*n;j++) cout<<id[j]<<' '; cout<<endl;
//			cout<<"re_id: "; for(int j=1;j<=2*n;j++) cout<<re_id[j]<<' '; cout<<endl;
//			cout<<"cnt[id]: "; for(int j=1;j<=2*n;j++) cout<<cnt[id[j]]<<' '; cout<<endl;
//			cout<<"l: "; for(int j=0;j<=2*n;j++) cout<<l[j]<<' '; cout<<endl;
//			cout<<"r: "; for(int j=0;j<=2*n;j++) cout<<r[j]<<' '; cout<<endl;
//			cout<<"ans: "<<ans[i-1]<<endl;int now = a[i];   // 当前值 int cnt_now = cnt[now];    // 当前数量 int tl = l[cnt_now], id_tl = id[tl];  // 边界,边界对应的值swap(id[tl], id[re_id[now]]);re_id[id_tl] = re_id[now];re_id[now] = tl;if(l[cnt_now] == r[cnt_now]) {l[cnt_now] = r[cnt_now] = -1;} else {l[cnt_now] ++;}if(r[cnt_now+1] == -1) {l[cnt_now+1] = r[cnt_now+1] = tl;} else {r[cnt_now+1] ++;}cnt[now] ++;now = a[i-k];  cnt_now = cnt[now];int tr = r[cnt_now], id_tr = id[tr];swap(id[tr], id[re_id[now]]);re_id[id_tr] = re_id[now];re_id[now] = tr;if(l[cnt_now] == r[cnt_now]) {l[cnt_now] = r[cnt_now] = -1;} else {r[cnt_now] --;}if(l[cnt_now-1] == -1) {l[cnt_now-1] = r[cnt_now-1] = tr;} else {l[cnt_now-1] --;}cnt[now] --;ans[i] = cnt[id[1]];} 
//		cout<<endl;
//		cout<<"a_now: "; for(int j=n-k+1;j<=n;j++) cout<<a[j]<<' '; cout<<endl;
//		cout<<"cnt: "; for(int j=1;j<=2*n;j++) cout<<cnt[j]<<' '; cout<<endl;
//		cout<<"id: "; for(int j=1;j<=2*n;j++) cout<<id[j]<<' '; cout<<endl;
//		cout<<"re_id: "; for(int j=1;j<=2*n;j++) cout<<re_id[j]<<' '; cout<<endl;
//		cout<<"cnt[id]: "; for(int j=1;j<=2*n;j++) cout<<cnt[id[j]]<<' '; cout<<endl;
//		cout<<"l: "; for(int j=0;j<=2*n;j++) cout<<l[j]<<' '; cout<<endl;
//		cout<<"r: "; for(int j=0;j<=2*n;j++) cout<<r[j]<<' '; cout<<endl;
//		cout<<"ans: "<<ans[n]<<endl;for(int d=1;d<=q;d++){int L, R; cin>>L>>R;R = L+k-1;cout<<k - ans[R]<<endl;}}
}

http://www.ppmy.cn/devtools/114284.html

相关文章

干货:分享6款ai论文写作助手,一键生成原创论文(步骤+工具)

写一篇论文是一个复杂的过程&#xff0c;涉及多个步骤&#xff0c;包括选题、研究、撰写、编辑和校对。AI可以在其中的一些步骤中提供帮助&#xff0c;但最终的论文还是需要人类作者的深入思考和创造性输入。以下是六款值得推荐的AI论文写作助手&#xff0c;其中特别推荐千笔-A…

一个有个性的使用工具thefuck@Ubuntu

这个工具名字可能有些粗鄙&#xff0c;不过真的有让人眼前一亮的功能。 当用户输入错误的命令时&#xff0c;TheFuck会根据上下文自动推测并给出正确的命令建议。 安装 apt update apt search thefuck apt install thefuck 使用 在错误命令下面直接输入thefuck即可。 不过…

springboot通过tomcat部署项目(包含jar、war两种方式,迄今为止全网最详细!2024更新..建议收藏,教学!万字长文!)

本博客参考的所有文章均已在结尾声明&#xff01;&#xff01;&#xff01; 在 Spring Boot 项目中&#xff0c;有两种常见的部署方式&#xff1a; 1、使用 Spring Boot 自带的 内置 Tomcat&#xff0c;将项目打包为 jar 并直接运行。 2、使用 外置 Tomcat&#xff0c;将项目打…

【算法专题】穷举vs暴搜vs深搜vs回溯vs剪枝

二叉树剪枝 LCR 047. 二叉树剪枝 - 力扣&#xff08;LeetCode&#xff09; 本题要求我们将全部为0的二叉树去掉&#xff0c;也就是剪枝&#xff0c;当我们举一个具体的例子进行模拟时&#xff0c;会发现&#xff0c;只关注于对其中一个子树的根节点进行剪枝&#xff0c;由于我…

Ubuntu 22.04上安装Python 3.10.x

在Ubuntu 22.04上安装Python 3.10.x可以通过以下步骤完成&#xff1a; 前言 本文由浪浪云赞助发布&#xff0c;我们特别感谢浪浪云的鼎力支持。浪浪云作为业界领先的云服务提供商&#xff0c;以其卓越的性能和可靠性&#xff0c;助力全球众多企业和开发者实现了业务的快速部署…

全网多少没买过的朋友!央视热播剧《凡人歌》大结局:我们一生,最该看透的7条生活真相——早读(逆天打工人爬取热门微信文章解读)

你买过吗&#xff1f; 引言Python 代码第一篇 洞见 央视热播剧《凡人歌》大结局&#xff1a;我们一生&#xff0c;最该看透的7条生活真相第二篇 市场很差 人很可怜结尾 绝了 这些我都没有买过 引言 时隔多日 又来啦 五天了 中秋假期真的很长呀 我多休了两天 美滋滋 但是别嫉妒…

IP协议及相关特性

IP协议负责地址管理和路由选择。它的组成为&#xff1a; 接下来我们将对其中较重要的部分进行介绍。 4位版本&#xff1a;这里的四位版本只有两个取值 分别为IPv4和IPv6&#xff0c;这两个额分别为不同的IP协议&#xff0c;但是现在主流的还是IPv4但是近年来IPv6在中国的普及率…

leetcode 199.二叉树的右视图

思路&#xff1a;伪层序遍历。 我们知道&#xff0c;在层序遍历的时候其实就是自上而下&#xff0c;自左而右的进行遍历树&#xff0c;但是&#xff0c;我们这里说的是右视图&#xff0c;其实就可以理解成&#xff0c;我们仿照层序遍历&#xff0c;自上而下&#xff0c;自右而…

Python中合并列表(list)的六种方法

列表是Python中强大的数据结构&#xff0c;很多时候我们要对它进行增、删、改、查&#xff0c;其中增是常见的操作&#xff0c;一般通过合并列表的方法来实现。那么&#xff0c;如何把2个列表合并成多个列表呢&#xff1f;今天我们就来学习一下六种不同的方法。 一、直接用 合…

提高数据集成稳定性:EMQX Platform 端到端规则调试指南

自 5.7.0 版本起&#xff0c;EMQX 支持了 SQL 调试&#xff0c;并支持在数据集成全流程中进行规则调试&#xff0c;使用户能够在开发阶段就全面验证和优化规则&#xff0c;确保它们在生产环境中的稳定高效运行。 点击此处下载 EMQX 最新版本&#xff1a;https://www.emqx.com/z…

docker镜像源

目前国内可用Docker镜像源汇总&#xff08;截至2024年8月&#xff09; - CoderJia docker.registry.cyou正常docker-cf.registry.cyou正常dockerpull.com正常dockerproxy.cn正常docker.1panel.live正常hub.rat.dev正常dhub.kubesre.xyz正常docker.hlyun.org正常docker.kejilio…

亚信软件测试实习面试记录

一、面试问题记录 1、首先是自我介绍&#xff0c;不用多说 2、技术问题 问得不深&#xff0c;简单来说几乎等于没问&#xff0c;只问了一句会不会***。 会Linux嘛&#xff08;应该可以自己回答的时候适当拓展的&#xff0c;但是我只老老实实说了会&#xff09;&#xff1b; 会…

IDEA Project不显示/缺失文件

问题&#xff1a;侧边栏project 模式下缺少部分文件 先点close project 打开项目所在目录&#xff0c;删除目录下的.idea文件夹 重新open project打开这个项目即可解决

MySQL慢查询日志

临时开启 -- 开启慢查询日志 SET GLOBAL slow_query_log ON; -- 设置慢查询日志的文件路径 SET GLOBAL slow_query_log_file /path/to/your/logfile.log; -- 设置慢查询阈值为2秒 SET GLOBAL long_query_time 2;永久开启 [mysqld] # 开启慢查询日志 slow_query_log 1 # 设…

二十种编程语言庆祝中秋节

二十种编程语言庆祝中秋节 文章目录 二十种编程语言庆祝中秋节中秋快乐&#xff01;家人们 &#x1f973;一 Python二 C三 C四 Java五 C#六 Perl七 Go八 Asp九 PHP十 JavaScript十一 JavaScript HTML十二 Visual Basic十三 早期 VB十四 Visual C十五 Delphi十六 Shell十七 Cobo…

AIGC生图基础知识

一、引言 AIGC&#xff0c;即AI-Generated Content&#xff0c;是一种利用大型预训练模型如生成对抗网络&#xff08;GAN&#xff09;、扩散网络&#xff08;Diffusion&#xff09;和语言大模型&#xff08;Transformer&#xff09;等人工智能技术&#xff0c;通过对大量数据进…

完整gpt应用(自用)

qrc.py 把gpt_qrc.qrc转化成gpt_qrc.py pyrcc5 -o icons_rc.py icons.qrc <RCC><qresource prefix"img"><file>img/53.png</file><file>img/ai.png</file><file>img/关闭.png</file><file>img/最小化.png&l…

物联网之Arduino编程语言、条件语句、循环语句、变量、数组、函数

MENU 注释变量条件语句if语句switch语句 循环语句for循环while循环 数组函数函数基本介绍常用函数介绍 总结 注释 当编写代码时&#xff0c;注释(comments)非常重要。注释是对代码的解释和说明&#xff0c;且对于其他开发者或者自己日后需要修改代码的时候&#xff0c;都非常有…

【代码】使用c#实现串口通信的基础模板

一、分享代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;using System.IO.Ports; using…

强制转换数据类型

1.转换为String 强制类型转换 指将一个数据类型强制转换为其它数据类型 类型转换主要指&#xff0c;将其它数据类型转换为 String Number Boolean 将其他数据类型转换为String 方法一&#xff1a; 调用被转换数据类型的toString()方法; 该方法不会影响到原变量&#…