题目链接:http://codeforces.com/contest/985
A:
暴力题吧,只需要在把黑色和白色的值都算一遍,最后取两种情况的min就可以了。
B:
模拟题,只需要每次枚举那个开关不动即可。
C:
只需要sort一下,想一下如何选取即可。举个栗子吧:
其中划竖线的地方就是临界点(刚好满足题意)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll a[maxn];
bool vis[maxn];
bool cmp(ll a,ll b)
{
return a<b;
}
int main()
{
int n,k;
ll l;
scanf("%d%d%I64d",&n,&k,&l);
for(int i=1;i<=n*k;++i)
{
scanf("%I64d",&a[i]);
}
sort(a+1,a+1+n*k);
ll ans=0;
int cnt=0;
for(int i=n*k-k+1;i>=1;i--)
{
if(a[i]-a[1]>l) continue;
if(i<n) break;
cnt=i;
break;
}
//printf("%d %d\n",n*k-k+1,cnt);
if(cnt)
{
memset(vis,0,sizeof(vis));
int flag=0,num=0;
for(int i=cnt;i>=1;i--)
{
if( (i-1)%k==0)
{
flag=i;
break;
}
}
//printf("%d %d\n",cnt,flag);
for(int i=1;i<=n*k;i+=k)
{
if(i>flag) break;
vis[i]=1;
ans+=a[i];
num++;
}
for(int i=cnt;i>=1;--i)
{
if(num==n) break;
if(vis[i]) continue;
vis[i]=1;
ans+=a[i];
num++;
}
}
printf("%I64d\n",ans);
return 0;
}
/*
4 5 3
1 1 2 2 1 2 2 3 3 4 4 4 5 5 5 5 5 5 6 6
*/
D:
二分一下,堆的最高值即可! 构造很关键
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,h,ans=0x7f7f7f7f7f7f7f7f;
bool check(ll mid)
{
ll ret,need;
if(mid>h)
{
need = ll(1.0*(h+mid)*(mid-h+1)/2+1.0*(mid-1)*mid/2);
ret= mid-h+mid;
}
else
{
need=ll(1.0*mid*(mid+1)/2);
ret=mid;
}
if(need>n) return 0;
ll last=n-need;
ret += last/mid+(last%mid>0);
if(ret<=ans)
{
ans=ret;
return 1;
}
return 0;
}
int main()
{
scanf("%I64d%I64d",&n,&h);
ll l=1 , r=int(2e9)+7,mid;
while(l<=r)
{
mid= (l + r)>>1;
if(check(mid)) l=mid+1;
else r=mid-1;
}
printf("%I64d\n",ans);
return 0;
}
E:
dp题吧,
dp[i]=a, 代表包含i的这堆的起始位置是谁。
转移就是
int pre=dp[i-m+1];
if(a[i]-a[pre]<=k) dp[i+1]=i+1;
else dp[i+1]=dp[i];
如果满足题意,那么下一个位置就可以做开头。
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+100;
int a[maxn];
bool cmp(int a,int b)
{
return a<b;
}
int dp[maxn];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;++i) dp[i]=1;
for(int i=m;i<=n;++i)
{
int pre=dp[i-m+1];
if(a[i]-a[pre]<=k) dp[i+1]=i+1;
else dp[i+1]=dp[i];
}
if(dp[n+1]==n+1) printf("YES\n");
else printf("NO\n");
return 0;
}