要是C没挂终测,我这场就。。。没有什么要是。C题读错题了。终测前6道rk47,终测完5道rk140。虽然上了86分,但是心里还是很sad。。。
A题:
没什么好说的。统计1~k的奇数和偶数个数。答案就是n*((k+1)/2)-(m*(k/2))。
B题:
考虑贪心,每次出现“101”这种情况我们就把后面的1改成0。这样10101这种情况我们只需要改一个,肯定是最优的。
C题:
这道题我居然读错了题 WAWAWA
就是对每一个a[i],若删除a[i]后,剩下的数的和为剩下的数中的最大数的两倍。则输出下标i。
对数组排序后,显然a[1]~a[n-1]的情况都是a[n]为最大。所以特判一下a[n]的情况删a[n-1]就可以了。
D题:给你n个数字,
每一轮删除k个数字(每一轮都删除一样的数字),求进行轮数最多的情况下每一轮删哪k个数。
用数组记录每个数字出现的次数。然后二分进行的轮数。注意输出的时候每个数字输出 次数/轮数 向下取整 次。
E题:
给你n道题。每道题的难度规定一个数字。
任意两场比赛的题目难度不能有相同的,但是每一场的题目难度必须相同。第一场如果是k道题,那么第i场就是k*(2的(i-1)次方)道题。
求题数最多的情况下,能用多少道题举办比赛。(并不一定举办的场数最多)
由于与数字大小无关,我们进行离散化,统计每个数字出现的次数并存到数组中。
排序。枚举第一场是几道题(1~出现次数最多的数字的次数)
然后用一个变量l记录>=当前需要数量的最小下标,暴力找能用多少题(在第一场的题数确定的情况下)。显然可以二分,又由于每次题数都要*2,所以总复杂度不会超过O(n*logn*logn)。
F1题:
n件物品,每种价值为a[i],你只能买正好x件,连续k件物品中必买一件。问你最多买多少价值的衣服。不满足条件输出-1。
显然可以暴力三维dp[i][j][k],表示前i天买了j件上一件是第k天买的最大价值。注意初始化的细节。
F2题:
显然上述思路中,确定买了j件之后,前i天能获得的最大价值是递增的。然后用一个单调队列压缩掉第三维,只要队头和当前天数i超过x天就出队即可。比赛的时候来不及写了。赛后1A。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=5010;
const ll mo=1e9+7;
int n,m,k,q,x;
ll a[maxn],dp[maxn][maxn];
ll sum;
ll c[maxn];
ll ans,ct,cnt,tmp,flag;
char s[maxn];
pair<int,ll>st[maxn*2];
int main()
{
ll T,cas=1;
//scanf("%d",&T);
//while(T--)
{
scanf("%d%d%d",&n,&k,&x);
memset(dp,-1,sizeof(dp));
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
dp[0][0]=0;
for(int z=1;z<=x;z++){
int aa=0,bb=-1;
st[++bb]=make_pair(0,dp[z-1][0]);
for(int i=1;i<=n;i++)
{
int t=max(0,i-k);
while(aa<=bb&&st[aa].first<t) aa++;
if(aa>bb) continue;
ll rr=st[aa].second;
if(rr>=0) dp[z][i]=rr+a[i];
while(aa<=bb&&st[bb].second<=dp[z-1][i]) bb--;
st[++bb]=make_pair(i,dp[z-1][i]);
}
}
ans=-1;
for(int i=max(0,n-k+1);i<=n;i++)
ans=max(ans,dp[x][i]);
printf("%lld\n",ans);
// if(flag) puts("Yes"); else puts("No");
}
return 0;
}