codeforces 1197D-Yet Another Subarray Problem

传送门:QAQQAQ

题意:给你一个序列,求一个子序列a[l]~a[r]使得该子序列的sum(l,r)-k*(r-l+1+m+1)/m值是在所有子序列中最大的,并输出最大值

思路:比赛的时候使用O(n)写的,但是被hack了,因为O(n)无法记录当前距离下一次-k还有多少,若用单调队列维护也不知道前面应该弹出多少(可能现在把前面弹出是最优的,但是到后面可能因为个数还没到m的倍数,把前面加进去又是最优的),所以我们考虑再加一维

法一:dp[i][j]表示序列到i截止,这一轮已经进行了j次取数(j=(len+m-1)%m),那么dp[i][j]维护的就是起点为s=i-j+1-m*t(t>=0)这个集合的最优,这样所有的dp[i][j]就可以维护以i截止的最优答案了

对于当前i更新有两种情况:第一种是只取当前这个a[i]这个在dp[i][1]特判即可

            第二种是还要取前面的,dp[i][j]从dp[i-1][j-1](因为dp[i-1][j-1]所维护的s集合和dp[i][j]所维护的s集合是一样的)转移即可(注意边界条件)

(之前HCY玄学又加了一层循环更新,一直看不懂,后来发现他虽然答案是对的,但m次更新中只有1次是有效的)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll inf=200000000000000;

int n,m;
ll ans=0,dp[300005][20],sum[300005],a[300005],k;

int main()
{
    scanf("%d%d%lld",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++) dp[i][j]=-inf;
    }
    dp[1][1]=a[1]-k;
    for(int i=2;i<=n;i++)
    {
        dp[i][1]=a[i]-k;
        for(int j=1;j<=min(i,m);j++)
        {
            if(j==1) dp[i][j]=max(dp[i][j],dp[i-1][m]+a[i]-k);
            else dp[i][j]=max(dp[i][j],dp[i-1][j-1]+a[i]);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) ans=max(ans,dp[i][j]);
    }
    cout<<ans<<endl;
    return 0;
}//

法二:

和比赛时我的思路很像,只不过这里多加了一层维护start_point%m=rnd,进行m次尺取法即可(在时间够的情况下,搞不清楚当前单调队列弹出几个是最优的,那么就枚举,这样就不用担心前面要弹出什么了,只需在len%m=0时判断是否要把起始点重置即可)

即如果当前的和减去k*t小于0,那么就重新开始,否则继续加

注意ans在每一次向后扩展时都要更新

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300005;
ll ans=0,n,a[N],m,k;
 
int main()
{
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int rnd=1;rnd<=m;rnd++)
    {
        ll len=0; ll now=0;
        for(int i=rnd;i<=n;i++)
        {
            if(len%m==0) if(now-len/m*k<0) now=0,len=0;
            now+=a[i]; len++;
            ans=max(ans,now-(len+m-1)/m*k);
        }
    }
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Forever-666/p/11241525.html

时间: 2024-08-30 17:30:59

codeforces 1197D-Yet Another Subarray Problem的相关文章

Codeforces Round #253 (Div. 2), problem: (B)【字符串匹配】

简易字符串匹配,题意不难 1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int main(){ 9 int i, j, k, t, n; 10 int num, flag, ans; 11 char a[300]; 12 sc

codeforces#253 D - Andrey and Problem里的数学知识

这道题是这样的,给主人公一堆事件的成功概率,他只想恰好成功一件. 于是,问题来了,他要选择哪些事件去做,才能使他的想法实现的概率最大. 我的第一个想法是枚举,枚举的话我想到用dfs,可是觉得太麻烦. 于是想是不是有什么规律,于是推导了一下,推了一个出来,写成代码提交之后发现是错的. 最后就没办法了,剩下的时间不够写dfs,于是就放弃了. 今天看thnkndblv的代码,代码很短,于是就想肯定是有什么数学规律,于是看了一下, 果然如此. 是这样的,还是枚举,当然是有技巧的,看我娓娓道来. 枚举的话

D. Yet Another Subarray Problem 思维 难

D. Yet Another Subarray Problem 这个题目很难,我比赛没有想出来,赛后又看了很久别人的代码才理解. 这个题目他们差不多是用一个滑动窗口同时枚举左端点和右端点,具体如下: 首先枚举0~m,这个是说更新的位置,如果是1 当m==3 就更新1 4 7 10... 如果是2,当m==3 就更新 2 6 8 11.... 最后都会被更新的. 核心代码 for (int j = 0; j < n - i; ++j) { s += sum[j]; if (j % m == 0)

Educational Codeforces Round 67 D. Subarray Sorting

Educational Codeforces Round 67 D. Subarray Sorting 传送门 题意: 给出两个数组\(a,b\),现在可以对\(a\)数组进行任意次排序,问最后能否得到\(b\)数组. \(n\leq 3*10^5,a\leq n.\) 思路: 首先注意到任意次排序可以等价于任意次交换两个相邻的数,当且仅当前一个数不小于后面一个数. 我一开始想的是按权值从小到大来构造,但最终发现这条路走不通. 正解就是比较直接的思路,按位置一个一个来匹配. 对于一个\(b_i\

[题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)

题目链接:https://codeforces.com/problemset/problem/1197/D 题意: 给你一个序列,求一个子序列 a[l]~a[r] 使得该子序列的 sum(l,r)-k*(r-l+1)/m(向上取整)的值是在所有子序列中最大的,并输出最大值 思路: 法一:动态规划 dp[i][j] 表示序列到i截止,这一轮已经进行了j次取数(j = (len+m-1)%m) 那么dp[i][j]维护的就是起点为 s = i-j+1-m*t (t>=0)这个集合的最优,这样所有的

CodeForces 1197 D Yet Another Subarray Problem

题面 不得不说CF还是很擅长出这种让人第一眼看摸不着头脑然后再想想就发现是个SB题的题的hhh(请自行断句). 设sum[]为前缀和数组,那么区间 [l,r]的价值为 sum[r] - sum[l-1] - k*上取整([r-(l-1)]/m). 或者表示 [l+1,r] 的价值更加简洁一些: sum[r] - sum[l] - k*上取整 ((r-l)/m). 表示的区间是什么并不重要,我们只在乎后者的最大值,当r确定的时候,值只与 sum[l] + k*上取整 ((r-l)/m) 有关. 我

Codeforces Round #427 (Div. 2) Problem C Star sky (Codeforces 835C) - 前缀和

The Cartesian coordinate system is set in the sky. There you can see n stars, the i-th has coordinates (xi, yi), a maximum brightness c, equal for all stars, and an initial brightness si (0 ≤ si ≤ c). Over time the stars twinkle. At moment 0 the i-th

Codeforces 776D:The Door Problem(DFS染色)

http://codeforces.com/problemset/problem/776/D 题意:有n个门,m个开关,每个门有一个当前的状态(0表示关闭,1表示打开),每个开关控制k个门,但是每个门确切的受两个开关控制,如果一个开关打开,那么原来关闭的门会打开,打开的门关闭,问是否存在一个情况使得所有的门打开. 思路:类似于01染色,把开关当成点,门当前的状态当成边权建图.初始先假设一个门的状态(初始假设为0和假设为1都是一样的,举几个例子就发现了),然后因为每个门受两个开关控制,所以可以推出

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h