题意:n个人,分成m组,多的人就不要了,每组的人都是顺序的,每组选出一个分最高的人,问你最少需要多少人他们的和>k
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<map>
#define INF 99999999
#define LL long long
#define maxn 200105
using namespace std;
int n,k;
int a[maxn];
int f[maxn][20];
void init()
{
for(int i=1;i<=n;i++)
{
f[i][0]=a[i];
}
for(int j=1;j<=20;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]);
}
}
}
int query(int l,int r)
{
int k=(int)(log(1.0*(r-l+1))/log(2.0));
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main()
{
while(scanf("%d %d",&n,&k)!=EOF)
{
if(n==-1&&k==-1)
break;
int sum=0;
int maxi=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
maxi=max(a[i],maxi);
}
LL ans;
int i,flag;
init();
if(sum<=k)
{
printf("-1\n");
continue;
}
if(maxi>k)
{
printf("1\n");
continue;
}
for(i=k/maxi;i<=n;i++)
{
flag=0;
ans=0;
for(int j=1;j<=i;j++)
{
ans+=query((j-1)*(n/i)+1,j*(n/i));
if(ans>k)
{
flag=1;
break;
}
}
if(flag)
break;
}
printf("%d\n",i);
}
return 0;
}
线段树版本
遇到的bug:求不同段的最大值时,段数搞错了,应该枚举段数,而不是n
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 205005
#define INF 0x3f3f3f3f
#define Mid (l+r)/2
#define lson step<<1
#define rson step<<1|1
#include <cstring>
#include <vector>
#define LL long long
using namespace std;
LL n;
LL k;
LL a[maxn];
LL tree[maxn<<2];
LL mini,maxi;
void pushup(int step)
{
tree[step]=max(tree[lson],tree[rson]);
}
void build(int l,int r,int step)
{
if(l==r)
{
tree[step]=a[l];
return ;
}
int mid=Mid;
build(l,mid,lson);
build(mid+1,r,rson);
pushup(step);
}
LL query(int l,int r,int left,int right,int step)
{
if(l==left&&r==right)
{
return tree[step];
}
int mid=Mid;
LL ans;
if(right<=mid)
{
ans=query(l,mid,left,right,lson);
}
else if(left>mid)
{
ans=query(mid+1,r,left,right,rson);
}
else
{
LL t1,t2;
t1=query(l,mid,left,mid,lson);
t2=query(mid+1,r,mid+1,right,rson);
ans=max(t1,t2);
}
return ans;
}
bool judge(int m)
{
LL sum=0;
int f=n/m;
for(int i=1;i<=m;i++)
{
LL t=query(1,n,(i-1)*f+1,f*i,1);
sum+=t;
}
if(sum>k)
return true;
else
return false;
}
void solve()
{
int L=0;
int H=n+1;
while(H-L>1)
{
int mid=(L+H)/2;
//cout << mid << endl;
if(judge(mid))
{
H=mid;
}
else
L=mid;
//cout << L << ' ' << H << endl;
}
cout << H << endl;
}
int main()
{
while(cin>>n>>k)
{
if(n<0&&k<0)
break;
LL ts=0;
mini=INF;
maxi=-1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
mini=min(a[i],mini);
maxi=max(a[i],maxi);
ts+=a[i];
}
if(ts<=k)
{
cout << -1 << endl;
continue;
}
build(1,n,1);
solve();
}
return 0;
}