第三次课ST表

1.描述

ST表是可重复贡献问题,采用了倍增动态规划的思想

可重复贡献问题:没一个元素会重复贡献,添加一些元素不会影响最终结果

可重复贡献问题应用:1.求最大公约数(gcd)

                             2.求区间最大值和最小值

可采取打表思想:预处理时间复杂度O(n log n) 查询时间复杂度O(1)

2.操作

1.预处理

f[i][j]表示以i为起点长度为2^j个元素的最大值

初始化:f[i][0]=a[i]

动态转移方程: f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1]);

本意来说就是求区间为从i开始,长度为2^j的区间最大值拆分成区间从i开始,长度为2^(j-1)的区间最大值和区间从i+2^(j-1)开始,长度为2^(j-1)的区间最大值的最大值

代码如下:

for(int j=1;j<=log2(n);j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		} 
	}
 2.查询

代码如下:

int k=log2(r-l+1);
int ans=max(f[l][k],f[r-(1<<k)+1][k]);
cout<<ans<<endl;

求区间[l,r]的最大值可以分成去区间[l,l+2^k-1]的最大值和区间[r-2^k+1,r]的最大值的最大值 

也就是求max(f[l][k],f[r-(1<<k)+1][k])

3.换底公式

log a ( b ) / log a ( c ) = log c ( b ) 

3.例题

A Magic Lamp

题目描述

kiki喜欢旅行。 有一天她发现了一盏神灯,可惜神灯里的精灵并不那么善良。 kiki必须回答一个问题,然后精灵才能实现她的一个梦想。

问题是:给你一个整数,你可以精确地删除 m 位数字。 剩余的数字将形成一个新的整数。 你应该把它减到最小,并且不允许更改数字顺序。 现在你能帮助kiki实现她的梦想吗?

输入描述

有若干组测试用例。

每个测试用例将包含一个给定的整数(最多可以包含 11001100 位数字。)和整数 m(如果整数包含 n 位数字,则 m 不会大于 n)。

给定的整数将不包含前导零。

输出描述

对于每种情况,在一行中输出您可以获得的最小结果。

如果结果包含前导零,则忽略它。

样例输入

178543 4

1000001 1

100001 2

12345 2

54321 2

样例输出

13

1

0

123

321

思路:

本题就是要保留n-m位,

将f数组定义为pair类型,存储数字和序号

 保留的第一位数字一定在(1,m+1)

第二位数字一定在(x+1,m+2)

#include <bits/stdc++.h>
using namespace std;
const int maxn=2001;
int a[maxn];
pair<char,int> f[maxn][maxn];
int main(){
	string s;
	int m;
	while(cin>>s>>m){
		for(int i=1;i<=s.size();i++){
			f[i][0]=make_pair(s[i-1],i);
		}
	    int n=s.size();
		for(int j=1;(1<<j)<=n;j++){
		    for(int i=1;i+(1<<j)-1<=n;i++){
			    f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		    }
	    }
	    int l=1,r=m+1,tmp=n-m;
	    bool flag=false;
	    while(tmp--){
	    	int k=log2(r-l+1);
	    	char ans=min(f[l][k],f[r-(1<<k)+1][k]).first;
	    	int ans2=min(f[l][k],f[r-(1<<k)+1][k]).second;
	    	if(ans!='0'||(ans=='0'&&flag)){
	    		cout<<ans;
	    		flag=true;
			}
			l=ans2+1;
			r++;
		}
		if(!flag) cout<<0;
		cout<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值