首页 > 其他分享 >abc345e 做题小计

abc345e 做题小计

时间:2024-03-18 19:34:27浏览次数:25  
标签:int max ll 小计 abc345e long 做题 define 501

F 比 E 简单 ,套路题。
考场不会 E 。自闭。

Luogu链接

题意已经讲得很清楚了。

在题解中,认为 \(m\) 等价于原题的 \(k\) 。

思考

第一步看题应该会想到贪心。
先去掉重复,然后会剩下一些相邻互不相同的,然后从小到大排序删除即可。

没错,考场上就是这样想的,直接吃了依托大的罚时

这样是不对的。
其实这样处理的问题是原问题的弱化版。
因为删除了 $l\to r $ 这一段后有可能 \(c_{l-1}=c_{r+1}\) 这不就错了吗。

那我做个集贸啊

观察到 \(k\le 500\) 肯定是出题人有意而为。

一段段取的问题 考虑 dp 。

Solution 1

通用套路。
我们定义状态 \(f_{i,j,0/1}\) 表示前 \(i\) 个数中是否删除 \(i\),并且已经删除了 \(j\) 个的最大价值。
那么显然有转移:
\(f_{i,j,0} = \max(f_{i-1,j,0},f_{i-1,j,1})+ w_i\)
\(f_{i,j,1} = \max([c_{i+1}\ne c_{k}]f_{k,j-(i-k),0})(\forall k\ge 0,j-(i-k)\ge 0)\)

时间复杂度 \(O(nm^2)\)

不是这式子一二项都有 \(k\) 我优化个集贸啊,还有个条件。
直接喜提 MLE TLE 大礼包。

Solution 2

从这开始就没想到了,上面是考场思路,这里是看了题解才知道的。

一二项有 \(k\) 不好优化?还有颜色判断?直接把颜色放成一维不就行了!
我们定义状态 \(f_{i,j,k}\) 表示前 \(i\) 个数 删除 \(j\) 个 最后颜色为 \(k\) 的方案。

你别看它好像是 \(O(n^3m)\) 的,实际是 \(O(n^2m)\) 的。

因为唯一一个转移的状态就是 \(f_{i,j,c_i}\) 其它直接从 \(i-1\) 的复制过来就行了。
这个转移很好写,看代码就能懂。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define N 200005
using namespace std;
int n,k,m;
int c[N],pos;
ll v[N];
ll maxx;
ll col[N],top,w[N];
ll f[501][501][501],ans;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d%lld",&c[i],&w[i]);
	memset(f,-127/3,sizeof f);
	f[0][0][0]=0;
	for(int i=1;i<=n;i++)
	{
		f[i][0][0]=0;
		for(int j=0;j<=m;j++)
		{
			if(j) for(int k=0;k<=n;k++) f[i][j][k]=f[i-1][j-1][k];
			for(int k=0;k<=n;k++)
				if(k^c[i]) f[i][j][c[i]]=max(f[i][j][c[i]],f[i-1][j][k]+w[i]);
		}
	}
	return 0;
}

Solution 3

新的 dp !
虽然翻新了,但是很难搞啊。
思考我们最终求的是什么,不就是 \(\max(f_{n,m,1\to n})\) 吗。
每次转移的时候不就是求 \(\max (f_{i-1,j,k\ne c_i})\) 吗
根据每次转移只会更新一个状态,其实发现有很多无用状态。

在转移时,明显,我们只需要记两个值:不同颜色的最大值和次大值。

这样思路似乎就明了了!
我们定义新状态 \(f_{i,j,0/1}\) 表示 \(f_{i,j,k}(\forall 0\le k\le n)\) 的最大值 / 次大值。保证次大值和最大值的颜色不同。其中记 \(g_{i,j}\) 表示最大值的颜色是什么。

分类讨论一下当前颜色和取的上一个,我们改一下上面的代码,就能实现 \(O(1)\) 转移了!

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define N 200005
using namespace std;
int n,k,m;
int c[N],pos;
ll w[N];
ll f[N-4][501][2],ans;
int g[N-4][501];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d%lld",&c[i],&w[i]);
	memset(f,-127,sizeof f);
	f[0][0][0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			if(j)
			{
				f[i][j][0]=f[i-1][j-1][0],f[i][j][1]=f[i-1][j-1][1];
				g[i][j]=g[i-1][j-1];
			}
			ll v;
			if(g[i-1][j]^c[i]) v=f[i-1][j][0]+w[i];
			else v=f[i-1][j][1]+w[i];
			if(v>f[i][j][0]) 
			{
				if(g[i][j]^c[i]) f[i][j][1]=f[i][j][0];
				f[i][j][0]=v,g[i][j]=c[i];	
			}
			else if(g[i][j]^c[i]) f[i][j][1]=max(f[i][j][1],v);
		}
	}
	if(f[n][m][0]<0) f[n][m][0]=-1;
	printf("%lld",f[n][m][0]);
	return 0;
}

Solution 4

然而这份代码被卡空间了。

改成滚动数组即可。
时间复杂度 \(O(nk)\)

#include<bits/stdc++.h>
#define ll long long
#define N 200005
using namespace std;
int n,k,m;
int c[N],pos;
ll w[N];
ll f[2][501][2],ans;
int g[2][501];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d%lld",&c[i],&w[i]);
	memset(f,-127,sizeof f);
	f[0][0][0]=0;
	for(int i=1;i<=n;i++)
	{
		int p=i&1,q=!p;
		for(int j=0;j<=m;j++)
		{
			f[p][j][0]=f[p][j][1]=-1e18;g[p][j]=0;
			if(j)
			{
				f[p][j][0]=f[q][j-1][0],f[p][j][1]=f[q][j-1][1];
				g[p][j]=g[q][j-1];
			}
			ll v;
			if(g[q][j]^c[i]) v=f[q][j][0]+w[i];
			else v=f[q][j][1]+w[i];
			if(v>f[p][j][0]) 
			{
				if(g[p][j]^c[i]) f[p][j][1]=f[p][j][0];
				f[p][j][0]=v,g[p][j]=c[i];
			}
			else if(g[p][j]^c[i]) f[p][j][1]=max(f[p][j][1],v);
		}
	}
	if(f[n&1][m][0]<0) f[n&1][m][0]=-1;
	printf("%lld",f[n&1][m][0]);
	return 0;
}

标签:int,max,ll,小计,abc345e,long,做题,define,501
From: https://www.cnblogs.com/g1ove/p/18081231

相关文章

  • 做题小计:ARC120D
    传送门:Luogu题意讲的很清楚了,不再赘述。首先我们看一下这个式子。\[\sum\limits|a_i-a_j|\]添加了绝对值,似乎不太好维护。如果还是看做一位位取的话,我们不知道当前的数比后面的数是小还是大,无法确定正负号。绝对值不好搞,就拆绝对值。\[\sum\limits_{i=1}^n(-1)^{[a_i<a_j]......
  • 3.15pht做题笔记
    3.15pht做题笔记C考虑先枚举学生\(j\),再枚举问题\(x\),接着枚举该问题回答相同的同学\(i\)根据鸽巢原理,每个同学有效枚举的次数肯定不会超过\(O(nk)\),所以总复杂度是\(O(n^2k)\)D先想确定\(k\)之后怎么做,从\(1\)到\(n\)枚举\(a_1\)的位置,每次只会交换两组......
  • 做题小计 ARC170E
    我觉得很强的题目。传送门:Luogu分析分析问题本质。根据大量推理,发现问题再描述这样一个东西:一开始有\(a,b\),一开始有\(p\)的概率使得\(a\)加一,\(1-p\)的概率使得\(b\)加一。进行\(n-1\)次操作,每次操作如下:有\(p\)的几率与上一次操作的数相同有\(1-p\)的......
  • 关于信息学奥赛中的一些做题思路
    观前须知Sugar_Cube的博客园主页背景介绍本文记录了笔者在刷题或比赛中运用到的一些做题思路可以适当参考正文LuoguP2048超级钢琴首先显然有\(\mathcal{O}(n^2)\)暴力枚举每个子段,然后选择其中前k大的那么可以发现有贪心策略:选择k次最大值那么考虑怎样求最大值想......
  • 做题笔记2024.03
    2024.03.12#1CapitalismCF1450E奇环显然无解有解就直接差分约束就行https://www.luogu.com.cn/record/150592177[2024.03.12#2LEGOndaryGrandmasterCF1615F]不是自己想的/kk看了题解,感觉都说这个转换是显然的,还是太菜考虑将所有偶数位的数先翻转一次,这样原来的操作......
  • 做题小计 arc172e
    传送门*2300牛逼打表题。这个式子很不可思议,让人无从下手。选择打表找规律。由于\(2\nmidX\)和\(5\nmidx\)这些数我们可以跳过通过打表前\(10000\)的数,我们发现似乎没有重复的。继续打表\(1000000\)也没有重复的。直接大胆猜想,\(10^9\)内的\(n^n\)是构成无冲......
  • 做题小计 arc170c
    *2000*dparc170c我觉得很妙的dp题目。Solution一眼下去,似乎所有\(1\)的位置是固定的,其余位置随便填,答案就是\(m^{count(1)}\)?这一步在\(m\gen\)的时候是对的。但是\(m<n\)的情况很不好搞。序列问题容易想到dp。看题目,考虑要记录什么值。发现\(mex\)很难搞......
  • 做题思路
    堆由开发人员申请和释放空间(容易内存泄露);栈由系统自动分配释放H5新增:语义化(header等);媒体(video等);canvas;表单控件(time,data等);存储(sessionStorage);websocket反转链表思路:把原链表分成三份:pre(原链表),cur·tmp(即将处理的链表cur.next=null),p(处理完的新链表);总结:原理挺简单的,但是要注......
  • 图的着色小计
    问题引入有\(n\)个小孩子,它们有\(m\)对讨厌关系,每对关系约定为小孩\(p\)与小孩\(q\)不能再一起玩。现在你要给这些小孩分组,求最少要分成几组才满足每组小孩都不会发生矛盾。问题抽象我们抽象这个问题。关系可以想到二分图,但是每对关系会互相约束,显然不行。那么可以......
  • 做题思路
    前序遍历:根节点,左节点,右节点中序遍历:左节点,根节点,右节点后序遍历:左节点,右节点,根节点总结:名称是依据根节点位置命名的,左节点永远在右节点前面快速排序:base,right,left三个节点。base与right比较,如果right比base大,左移;反之,和left替换,left右移;base和left比较,比base大,和right替......