Codeforces Round #837 (Div. 2) B题题解(利用dp)

该问题是一个关于计算数组中满足特定条件的子序列数量的算法题。利用动态规划,通过状态f[i]表示以i结尾且满足条件的子序列个数。首先预处理数组w,找到每个位置i左边最大的不认识的元素,然后通过状态转移更新f[i],最后累加所有f[i]得到答案。
摘要由CSDN通过智能技术生成

题目链接:Problem - B - Codeforces

题意概括:

        本题题意是求给定的数组中范围内都认识(满足条件)的子序列的数量。

思路:
        我们可以先分析如果用dp来解,那么我们怎么表示状态,通过题目分析我们可以用 f[i] 来进行状态表示,其中,f[ i ] 指的是以 i 结束的满足条件的子序列的个数。而对于状态转移而言,我们对于每一个 i ,只有两种处理,一种是它没有不认识的,另一种是它有认识的,因为 i 本身就是一个符合条件的答案,所以我们对于每一个 i 都要先取为1,然后如果 i 没有认识的,那么就这样更新:f[i] = f[i - 1] + 1, 反之,就用if(i >= w[i])f[i] = i - w[i] 更新,其中,我们会先将有不认识的 i 进行预处理,使它对应的是左边最大的不认识的, 然后就可以使用如上的状态转移方程,最后将从1 到 n 的所有个数加起来输出即可。

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>

using namespace std;

typedef long long LL;

const int N = 1e5 + 10;

int f[N], w[N];

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		memset(w, 0, sizeof w);

		for (int i = 0; i < m; ++i) {
		    int x, y;
			scanf("%d%d", &x, &y);
			if(x > y) {int k= x; x = y, y = k;}   //记录所有的不认识情况
            w[y] = w[y] > x ? w[y] : x;
		}
		
		int ma = 0;
		for(int i = 1; i <= n; ++ i){
		    ma = ma < w[i] ? w[i] : ma;
		    w[i] = w[i] > ma ? w[i] : ma;       //预处理使得i对应左边最大不符合的数
		}

		for (int i = 1; i <= n; ++i){
			f[i] = 1;
			if (w[i] == 0) f[i] = f[i - 1] + 1;    //dp状态转移过程
			else if(i >= w[i])f[i] = i - w[i];
		}
		LL ans = 0;
		for (int i = 1; i <= n; ++i) ans += f[i];     //将结果累加输出
		cout << ans << endl;
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dawpro_加薪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值