首页 > 其他分享 >题解:[P11311 漫长的小纸带]

题解:[P11311 漫长的小纸带]

时间:2024-11-24 21:13:47浏览次数:8  
标签:cnt 200005 ++ 题解 元素 纸带 P11311 pos 一段

P11311 漫长的小纸带

题意:

有一个长度 \(n\) 的序列 \(a\),将 \(a\) 分成若干段,使得所有段价值和最小,定义价值为一段内元素数量的平方。

思路:

显然能用动态规划来计算答案,设 \(f[i]\) 表示到第 \(i\) 个位置所获得的最小价值,考虑怎么转移。

最直接的就是从 \(1\) 到 \(i-1\) 枚举断点 \(j\),设最后一段为 \(S\),有 \(f[i]=min(f[j]+|S|^2)\),很遗憾它的时间复杂度是 \(O(n^2)\) 的,过不了该题。

我们发现答案最劣是 \(n\),即每个数字各成一段。对于一段 \(S\) 的贡献是 \(|S|^2\) 那么显然 \(|S|\) 不应大于 \(\sqrt{n}\),那么转移只需从 \(1\) 到 \(\sqrt{n}\) 枚举最后一段元素个数即可。并且在元素个数相同的情况下,最后一段的长度越长,答案越优。

那么我们就需维护从 \(i\) 开始向前有 \(j\) 个元素时的最长长度,因为 \(i\) 是顺序枚举的,那么我们只需考虑新加入元素在之前的最后一段是否出现过,若出现过不做改变,否则从前向后删直到删去一个元素为止,具体可以看代码。

注意:

  1. 因为此题 \(1\le a[i]\le10^9\),所以需要离散化。

  2. 有一种写法是用一个类似桶的东西维护特定元素个数的最后一段的最长长度,大体代码长这样:

if(++cnt[j][a[i]]==1) {
	if(++C[j]>j) {
		while((--cnt[j][a[pos[j]]])!=0) pos[j]++;
		pos[j]++, C[j]--;
	}
}

不知为何经过一番卡常我也没过(也有可能是我的问题)。

  1. 此题有个双倍经验

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n, a[200005], pos[200005], pre[200005], last[200005], nex[200005], cnt[200005], f[200005];
//pos[i]表示最后一段有i个元素时的最长长度(我顺便用pos辅助了下离散化)
//cnt[i]表示pos[i]对应的元素个数 
//last[i]表示i的上一次出现位置 
//pre[i]表示与i位置相同的数的上一次出现位置,nex[i]表示下一次出现位置 
void discretization() { //离散化 
	ll cnt=0;
	map <ll, bool> vis;
	for(int i=1; i<=n; i++) if(!vis[a[i]]) {
		vis[a[i]]=1;
		pos[++cnt]=a[i];
	}
	sort(pos+1, pos+cnt+1);
	for(int i=1; i<=n; i++) a[i]=lower_bound(pos+1, pos+cnt+1, a[i])-pos;
}
int main() {
	cin >> n; 
	for(int i=1; i<=n; i++) cin >> a[i];
	discretization(); //离散化 
	for(int i=1; i<=n; i++) { //计算相关数组 
		pre[i]=last[a[i]];
		nex[last[a[i]]]=i;
		last[a[i]]=i;
		nex[i]=n+1;
	}
	memset(f, 0x3f, sizeof(f));
	memset(pos, 0, sizeof(pos));
	f[0]=0;
	ll t=sqrt(n);
	for(int i=1; i<=t; i++) pos[i]=1;
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=t; j++) {
			if(pre[i]<pos[j]) cnt[j]++; //这个数上一次出现不在最后一段内 
			if(cnt[j]>j) { //元素个数超过j个 
				while(nex[pos[j]]<i) pos[j]++; //nex[pos[j]]<i说明在最后一段内该元素有一个以上,删去它不改变元素数量,否则改变 
				pos[j]++, cnt[j]--;
			}
			if(cnt[j]==j) f[i]=min(f[i], f[pos[j]-1]+j*j);
		}
	}
	cout << f[n];
	return 0;
}

标签:cnt,200005,++,题解,元素,纸带,P11311,pos,一段
From: https://www.cnblogs.com/anins/p/18566367

相关文章

  • 读数据质量管理:数据可靠性与数据质量问题解决之道10数据平台
    1.      数据平台1.1.        让你能够从摄取数据到分析数据的整个过程中全面管理数据的技术组合1.2.        数据平台的要求随着业务的变化而变化1.3.        数据栈分为6层1.3.1.          数据摄取1.3.1.1.     ......
  • 读数据质量管理:数据可靠性与数据质量问题解决之道09数据可靠性
    1.      数据可靠性1.1.        数据可靠性指的是一个组织在整个数据生命周期中提供高数据可用性和健康状况的能力1.1.1.          是高数据质量带来的结果1.1.1.1.           高质量的大数据是这个大规模转型平台的核心1.1.2. ......
  • 2018 ICPC南京区域赛题解 更新至 8 题
    2018ICPC南京区域赛题解更新至8题The2018ACM-ICPCAsiaNanjingRegionalProgrammingContest目录2018ICPC南京区域赛题解更新至8题The2018ACM-ICPCAsiaNanjingRegionalProgrammingContestPrefaceProblemA.AdrienandAustinProblemD.CountryMeowProblem......
  • 题解:[ARC188C] Honest or Liar or Confused
    乍一看以为是3-SAT不可做,动动脑子发现是2-SAT(鉴于本题解书写时洛谷题面暂无中文翻译,为避免可能的歧义或困惑,先对本题解中的译法进行约定:英文题面中“honestvillager”或日文题面中“正直者”译为“诚实村民”。英文题面中“liar”或日文题面中“嘘つき”译为“撒谎村民”......
  • CF1328题解
    CF1328A简单题,我们用\(b-a%b\)的余数即可,注意特判\(a%b==0\)即可CF1328B细节蛮多的,我们可以发现最终个数可以写成\(1+2+3+\dots+(p-1)+p+g\)最后\(n-p\)就是第一个b的位置,\(n-g\)就是第二个b的位置,可以推式子然后\(O(n)\)求但是我选择二分查找g,然后注意一下细节......
  • CF 1638 题解
    CF1638题解AReverse贪心的想,找到第一个\(a_i\not=i\)的位置,然后操作\([i,pos_{a_i}]\)这个区间即可.BOddSwapSort由于只能交换奇数和偶数,奇数偶数内部的相对位置不能改变,因此合法的充要条件是奇数之间已经有序,偶数亦然.CInversionGraph由于有效树边只......
  • [CodeForces] CF21 题解
    这次不放难度了。因为我懒A.JabberID【题目大意】一个地址由<username>@<hostname>[/resource]组成,其中[/resource]可以被省略。<username>字段允许大写、小写字母,数字、下划线,其长度应在\(1\)到\(16\)之间。<hostname>字段允许用.来分隔。每一段的要求同<u......
  • LeetCode题解:29.两数相除【Python题解超详细,位运算、二分查找法、递归法】,知识拓展:位
    题目描述        给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。返回被除数 dividend 除以除数 div......
  • 【题解】CF2031
    Atag:签到题注意到定住一个值后,左边的值全都得改,右边的值也全都得改注意到,定住的越多,需要改的就越少所以开桶记一下哪个值最多就行Btag:诈骗诈骗签到题读完题容易产生naive结论:当且仅当错位的两个地方相邻可以修复,其余情况全部无法修复感觉真不了一点,于是找三个数ABC......
  • 读数据质量管理:数据可靠性与数据质量问题解决之道13数据沿袭
    1. 数据沿袭1.1. MyDoom的病毒1.2. 现在,许多团队甚至整个公司都在使用数据,这要求数据管理的方式要更便于合作,同时也更不容许发生错误1.3. 从采用dbt和ApacheAirflow等开源工具来实现数据转换和编排,到使用Snowflake和Databricks等云端数据仓库和数据湖1.4. 数据仪表板和......