区间DP问题+基础算法详解

状态数组

状态表示数组DP[N][N],一般是二维,表示从i到j对应的答案数

对于区间合并问题.状态转移方程一般是,将一个大区间分成两个小区间,这两个小区间的状态已经计算出,思考这两个小区间计算出大区间的状态;

插入知识点:二叉树的三种遍历
先序遍历:根左右
中序遍历:左根右
后序遍历:左右根

中午没睡觉,下午脑子昏昏沉沉的,看不懂区间dp了,所以选择把算法提高课的基础算法重新看一遍

下面这个问题有关数据溢出的知识

## 64位整数乘法
输出一个整数,表示a*b mod p的值。

数据范围
1≤a,b,p≤1018
ll a,b,p;
	cin>>a>>b>>p;
	ll ans = 0;
	while(b)
	{
	    if(b&1)
	    {
	      ans = (ans+a)%p;
	    }
	    a = (a<<1)%p;//这里最好用a<<1,而不是写a*2,因为a*2可能会超出数据范围,而a<<1永远不会超出数据范围
	    //如果当前位是64位,那他不会变成65位,因为多的那一位会被挤掉(因为被挤掉的那一位表示的数值肯定是大于p的,取模之后也肯定是会被去掉,所以不影响答案),然后经过取模,得到正确的答案
	    b>>=1;
	}

RMQ算法(快速求区间最大值)

for (int i = 0; i <= 18; i++)
	{
		for (int j = 1; j + (1 << i) - 1 <= n; j++)
		{
			if (!i)
			{
				f[j][i] = a[j];
			}
			else
			{
				f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);
			}
		}
	}

#排序

问题一 环形均分纸牌问题:
一共有n个人围成一圈,每个人a[i]张纸牌,如果最终每个人纸牌数量相同,那么需要互相传递的纸牌总数是多少.

for (int i = 1; i <= n; i++)
	{
		a[i] += a[i - 1];//前缀和,前i个人一共有多少张纸牌
	}
	if (a[n] % n)
	{
		return -1;//如果不能均分,则直接退出
	}
	c[1] = 0;
	int avg = a[n] / n;//最终每个人多少张牌
	for (int i = 2; i <= n; i++)
	{
		c[i] = a[i - 1] - (i - 1) * avg;///重点/,c[i]表示如果让前i-1个人满足要求,那么第i个人需要给他们多少张,或者他们给第i个人多少张
	}
	sort(c+1,c+1+n);//排序之后,找中位数
	ll sum = 0;
	for (int i = 1; i <= n; i++)
	{
		sum += abs(c[i] - c[(n+1)/2]);//对数组c进行操作,记住就行,
	}
	return sum;

一个大根堆一个小跟堆实现快速查找中位数

	if(p.empty()||a<=p.top())
		p.push(a);
		else q.push(a);
		
		if(p.size()>q.size()+1)
		{
		    int k = p.top();
		    p.pop();
		    q.push(k);
		}
		if(q.size()+1>p.size())
		{
		    int k = q.top();
		    q.pop();
		    p.push(k);
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值