您的位置:首页 > 其它

HDU 3486 RMQ+二分

2016-06-15 15:34 375 查看
点击打开链接

题意:n个人,分成m组,多的人就不要了,每组的人都是顺序的,每组选出一个分最高的人,问你最少需要多少人他们的和>k

思路:因为要人数最少,直接想到了二分去求解,然后查询区间的最大值可以用RMQ直接快速查询,但是过了之后看讨论发现二分的是错的,好心人的数据是这样的

10 1500

1 1 1 1 1000 1000 1 1 1 1

明显分成两组两个人就可以了,但是我的AC代码输出的是6,看了看发现里面的数其实是不符合单调的性质的,所以不正确,然后翻了翻有人说枚举组数就可以过,这数据不敢恭维,不正确的算法以及相当暴力的写法竟然都可以过,有人有正确解法求告知,这里贴个二分的
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=200010;
int dp[maxn][20],num[maxn];
void RMQ_init(int n){
for(int i=1;i<=n;i++)
dp[i][0]=num[i];
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)-1<=n;j++){
dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
}
}
}
int RMQ(int le,int ri){
int k=0;
while((1<<(k+1))<=ri-le+1) k++;
int ans1=max(dp[le][k],dp[ri-(1<<k)+1][k]);
return ans1;
}
bool judge(int n,int m,int k){
int t=m,sum=0,l=n/m;
for(int i=0,j=1;i<t;i++,j+=l){
int ans=RMQ(j,j+l-1);
sum+=ans;
}
if(sum>k) return 1;
return 0;
}
int main(){
int n,k;
while(scanf("%d%d",&n,&k)!=-1){
if(n<0&&k<0) break;
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
RMQ_init(n);
if(judge(n,n,k)==0) printf("-1\n");
else{
int le=1,ri=n;
while(le<=ri){
int mid=(le+ri)>>1;
if(judge(n,mid,k)) ri=mid-1;
else le=mid+1;
}
printf("%d\n",le);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: