「CF1197D」Yet Another Subarray Problem【分治或dp】

D. Yet Another Subarray Problem

time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output

You are given an array a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an and two integers ? and ?.

You can choose some subarray a l , a l + 1 , … , a r − 1 , a r a_l,a_{l+1},…,a_{r-1},a_r al,al+1,,ar1,ar.

The cost of subarray a l , a l + 1 , … , a r − 1 , a r a_l,a_{l+1},…,a_{r-1},a_r al,al+1,,ar1,ar is equal to ∑ i = l r a i − k × ⌈ r − l + 1 m ⌉ \sum_{i=l}^{r}{a_i}-k\times \lceil \frac{r-l+1}{m}\rceil i=lraik×mrl+1,where ⌈ x ⌉ \lceil x \rceil x is the least integer greater than or equal to x x x.

The cost of empty subarray is equal to zero.

For example, if m = 3 , k = 10 m=3, k=10 m=3,k=10 and a = [ 2 , − 4 , 15 , − 3 , 4 , 8 , 3 ] a=[2,−4,15,−3,4,8,3] a=[2,4,15,3,4,8,3], then the cost of some subarrays are:

a 3 … a 3 : 15 − k ⌈ 1 3 ⌉ = 15 − 10 = 5 ; a_3…a_3:15−k\lceil \frac{1}{3} \rceil=15−10=5; a3a3:15k31=1510=5;
a 3 … a 4 : ( 15 − 3 ) − ⌈ 1 3 ⌉ = 12 − 10 = 2 ; a_3…a_4:(15−3)−\lceil \frac{1}{3} \rceil=12−10=2; a3a4:(153)31=1210=2;
a 3 … a 5 : ( 15 − 3 + 4 ) − ⌈ 1 3 ⌉ = 16 − 10 = 6 ; a_3…a_5:(15−3+4)−\lceil \frac{1}{3} \rceil=16−10=6; a3a5:(153+4)31=1610=6;
a 3 … a 6 : ( 15 − 3 + 4 + 8 ) − ⌈ 1 3 ⌉ = 24 − 20 = 4 ; a_3…a_6:(15−3+4+8)−\lceil \frac{1}{3} \rceil=24−20=4; a3a6:(153+4+8)31=2420=4;
a 3 … a 7 : ( 15 − 3 + 4 + 8 + 3 ) − ⌈ 1 3 ⌉ = 27 − 20 = 7. a_3…a_7:(15−3+4+8+3)−\lceil \frac{1}{3} \rceil=27−20=7. a3a7:(153+4+8+3)31=2720=7.
Your task is to find the maximum cost of some subarray (possibly empty) of array a a a.

Input

The first line contains three integers n , m , a n d   k ( 1 ≤ n ≤ 3 × 1 0 5 , 1 ≤ m ≤ 10 , 1 ≤ k ≤ 1 0 9 ) n, m, and\ k (1\leq n \leq 3\times 10^5,1\leq m \leq 10,1\leq k\leq 10^9) n,m,and k(1n3×105,1m10,1k109).

The second line contains n n n integers a 1 , a 2 , … , a n ( − 1 0 9 ≤ a i ≤ 1 0 9 ) a_1,a_2,…,a_n (−10^9\leq a_i \leq10^9) a1,a2,,an(109ai109).

Output

Print the maximum cost of some subarray of array a a a.

Examples

input
7 3 10
2 -4 15 -3 4 8 3
output
7
input
5 2 1000
-13 -4 -9 -20 -11

output

0

题意

  • 给你一个数组,以及给你 m , k m,k m,k,求下面这个式子的最大值
    ∑ i = l r a i − k × ⌈ r − l + 1 m ⌉ \sum_{i=l}^{r}{a_i}-k\times \lceil \frac{r-l+1}{m}\rceil i=lraik×mrl+1

题解

  • 由于 1 ≤ m ≤ 10 1\leq m \leq 10 1m10,可以考虑分治解决这个问题,分治合并的时候,先处理左区间每一个点的后缀和,然后计算后缀对应区间的长度 % m \%m %m意义下的上式最大值,然后扫右边的时候,枚举左边(也就是区间 [ l , m i d ] [l,mid] [l,mid])区间的长度 % m \%m %m意义下的长度,取个 m a x max max就行了,时间复杂度 O ( n m log ⁡ n ) O(nm \log n) O(nmlogn)
  • 还可以考虑 d p dp dp解决这个问题,就是定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示以i为右端点,左端点 l l l满足 ( r − l + 1 ) % m = j (r-l+1)\%m=j (rl+1)%m=j的上述函数最大值,转移的时候考虑从右侧第一个 m m m分段内转移还是 i − m i-m im前转移取最大就行了

分治解法代码

#include
 
using namespace std;
const int maxn=3e5+10;
 
int n,m;
long long a[maxn],k;
long long cur[100],sum[maxn];
 
int solve(int b)
{
    return b%m==0?b/m:b/m+1;
}
 
long long dfs(int l,int r)
{
    if(l==r) return a[l]-k;
    int mid=(l+r)>>1;long long res=-1e18;
    for(int i=0;i<m;i++) cur[i]=-1e18;sum[mid+1]=0;
    for(int i=mid;i>=l;i--) {
        sum[i]=a[i]+sum[i+1];
        cur[(mid-i+1)%m]=max(cur[(mid-i+1)%m],sum[i]-k*solve(mid-i+1));
    }
    sum[mid]=0;
    for(int i=mid+1;i<=r;i++) {
        int now=(i-mid)%m;sum[i]=sum[i-1]+a[i];
        for(int j=0;j<m;j++){
            if(j==0) res=max(res,cur[j]+sum[i]-k*solve(i-mid));
            else {
                if(j+now>m) res=max(res,cur[j]+sum[i]-k*solve(i-mid));
                else res=max(res,cur[j]+sum[i]-k*((i-mid)/m));
            } 
        }
    }
 
    return max(res,max(dfs(l,mid),dfs(mid+1,r)));
}
 
int main()
{
    scanf("%d %d %lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    printf("%lld\n",max(0LL,dfs(1,n)));
}

dp代码

#include

using namespace std;
const int maxn=3e5+10;

int n,m,k,a[maxn];
long long dp[maxn][12],sum[maxn];

int main()
{
    scanf("%d %d %d",&n,&m,&k);long long ans=0;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
    for(int i=1;i<=n;i++) {
        if(i-m>=0) dp[i][0]=max(dp[i][0],dp[i-m][0]+sum[i]-sum[i-m]-k);
        for(int j=1;j<m;j++) {
            if(i-j>=0) dp[i][j]=max(dp[i][j],sum[i]-sum[i-j]-k);
            if(i>=m) dp[i][j]=max(dp[i][j],sum[i]-sum[i-m]-k+dp[i-m][j]);
        }
        for(int j=0;j<m;j++) ans=max(ans,dp[i][j]);
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(分治,dp)