RMQ

1、HDU 3486

题意:

    n个人组成的序列,每一个元素有一个权值,现在要将这n个数分成m段(不能整除的去掉),

且要求这m段每段的最大值相加求和结果>K。求最小的M。

数据范围:N<=2e5,K<=1e9,Vi>=0。

思路:

      首先明确m越小,也就是每个组的人数尽可能的多。我们可以枚举M,

然后求解当前M下所获得的权值之和并与K相比较,如果符合要求,直接break,

否则,进入下一层循环的M。M的最小值==K/序列中权值的最大值,M<=2e5,

时间复杂度O(M*M*LogN)。时间复杂度好高的样子,不过大部分题解都是这

样鸭。

2、HDU 3193

题意:

           n个元素,每个元素由两个权值构成,

问这n个元素中有几个元素满足没有其他元素

严格小于它。(N<=1e4)

思路:

        显然可以按照某一个权值排序,然后遍历这n个元素,对于每一个元素,

二分找他前面权值first比他小(没有等于)的最后一个数,然后从找到的这个

数往前的区间内做RMQ找最小值,看是不是比当前判断的数的小。没啥东西

,,,应该能做出来吧。

AC代码(状态不好?WA了这么多次,心不静)

#include <cstdlib>
#include <iostream>
#include<algorithm>
#include <set>
#include <queue>
#include <stack>
#include<vector>
#include<map>
#include<ctime>
#include<cmath>
/** -?£- **/
#define LL long long
#define par pair<int,int>
#define INF 0x3f3f3f3f
#define io ios::sync_with_stdio(false)
using namespace std;
const int N=2e5+100;
const int M=4e6+100;
par a[N];
bool cmp(par xx,par yy)
{
	if(xx.first==yy.first)return xx.second<yy.second;
	return xx.first<yy.first;
}
int dp[N][35];
int search(int x,int y)
{
	int t=log(y-x+1)/log(2);
	return min(dp[x][t],dp[y-(1<<t)+1][t]);
}
par ans[N];
int tot;
int main()
{
	int n;
	
	while(cin>>n)
	{
		tot=0;
		
		for(int i=1;i<=n;++i)cin>>a[i].first>>a[i].second;
		sort(a+1,a+1+n,cmp);
		for(int i=1;i<=n;++i)dp[i][0]=a[i].second;
	
		int t1=log(n)/log(2)+1;	
		for(int j=1;j<t1;++j)
			for(int i=1;i+(1<<j)-1<=n;++i)//模板敲错好几遍 
			{
				dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
			}
		int mini=INF;
		for(int i=1;i<=n;++i)
		{
			if(i==1)
			{
				ans[++tot].first=a[i].first;
				ans[tot].second=a[i].second;
				continue;
			}
			int l=1,r=i;
			int index=1;
			while(l<=r)//脑子有点乱,这地方没想清楚,,, 
			{
				
				int mid=(l+r)/2;
				if(a[mid].first==a[i].first)r=mid-1,index=mid;
				else if(a[mid].first<a[i].first)l=mid+1;
				else r=mid-1;
			}
			if(index==1)
			{
				ans[++tot].first=a[i].first;
				ans[tot].second=a[i].second;
				continue;
			}
			else index-=1;
			
			//cout<<i<<" "<<index<<endl;
			int tmp=search(1,index);
			if(a[i].second<=tmp)
			{
				ans[++tot].first=a[i].first;
				ans[tot].second=a[i].second;
			}
			
			
		}
		cout<<tot<<endl;
		sort(ans+1,ans+1+tot,cmp);
		for(int i=1;i<=tot;i++)cout<<ans[i].first<<" "<<ans[i].second<<endl;
	
		
	}
	return 0;
}

3、HDU - 2888(二维RMQ)

题意:子矩阵的最值问题,二维RMQ模板。

4、HDU - 3183(思维题)

题意:N个数(N<=1000),从中去掉m个数,使得剩余的数组成的数最小。

思路:

      贪心就不说了,找ai>ai+1的情况。

      RMQ的话也没啥好说的,想不到没法做,,,做积累:

最后n-m个数组成的序列中第一个元素一定在原序列1~m+1

中出现,以此类推不断找最小值。为什么?鬼知道。

,,,,,,

 

 

  

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值