Codeforces 1384B2. Koa and the Beach (Hard Version)(DP)

The only difference between easy and hard versions is on constraints. In this version constraints are higher. You can make hacks only if all versions of the problem are solved.

Koa the Koala is at the beach!

The beach consists (from left to right) of a shore, 𝑛+1 meters of sea and an island at 𝑛+1 meters from the shore.

She measured the depth of the sea at 1,2,…,𝑛 meters from the shore and saved them in array 𝑑. 𝑑𝑖 denotes the depth of the sea at 𝑖 meters from the shore for 1≤𝑖≤𝑛.

Like any beach this one has tide, the intensity of the tide is measured by parameter 𝑘 and affects all depths from the beginning at time 𝑡=0 in the following way:

For a total of 𝑘 seconds, each second, tide increases all depths by 1.
Then, for a total of 𝑘 seconds, each second, tide decreases all depths by 1.
This process repeats again and again (ie. depths increase for 𝑘 seconds then decrease for 𝑘 seconds and so on …).
Formally, let’s define 0-indexed array 𝑝=[0,1,2,…,𝑘−2,𝑘−1,𝑘,𝑘−1,𝑘−2,…,2,1] of length 2𝑘. At time 𝑡 (0≤𝑡) depth at 𝑖 meters from the shore equals 𝑑𝑖+𝑝[𝑡mod2𝑘] (𝑡mod2𝑘 denotes the remainder of the division of 𝑡 by 2𝑘). Note that the changes occur instantaneously after each second, see the notes for better understanding.

At time 𝑡=0 Koa is standing at the shore and wants to get to the island. Suppose that at some time 𝑡 (0≤𝑡) she is at 𝑥 (0≤𝑥≤𝑛) meters from the shore:

In one second Koa can swim 1 meter further from the shore (𝑥 changes to 𝑥+1) or not swim at all (𝑥 stays the same), in both cases 𝑡 changes to 𝑡+1.
As Koa is a bad swimmer, the depth of the sea at the point where she is can’t exceed 𝑙 at integer points of time (or she will drown). More formally, if Koa is at 𝑥 (1≤𝑥≤𝑛) meters from the shore at the moment 𝑡 (for some integer 𝑡≥0), the depth of the sea at this point — 𝑑𝑥+𝑝[𝑡mod2𝑘] — can’t exceed 𝑙. In other words, 𝑑𝑥+𝑝[𝑡mod2𝑘]≤𝑙 must hold always.
Once Koa reaches the island at 𝑛+1 meters from the shore, she stops and can rest.
Note that while Koa swims tide doesn’t have effect on her (ie. she can’t drown while swimming). Note that Koa can choose to stay on the shore for as long as she needs and neither the shore or the island are affected by the tide (they are solid ground and she won’t drown there).

Koa wants to know whether she can go from the shore to the island. Help her!

Input
The first line of the input contains one integer 𝑡 (1≤𝑡≤104) — the number of test cases. Description of the test cases follows.

The first line of each test case contains three integers 𝑛, 𝑘 and 𝑙 (1≤𝑛≤3⋅105;1≤𝑘≤109;1≤𝑙≤109) — the number of meters of sea Koa measured and parameters 𝑘 and 𝑙.

The second line of each test case contains 𝑛 integers 𝑑1,𝑑2,…,𝑑𝑛 (0≤𝑑𝑖≤109) — the depths of each meter of sea Koa measured.

It is guaranteed that the sum of 𝑛 over all test cases does not exceed 3⋅105.

Output
For each test case:

Print Yes if Koa can get from the shore to the island, and No otherwise.

You may print each letter in any case (upper or lower).

Example
inputCopy
7
2 1 1
1 0
5 2 3
1 2 3 2 2
4 3 4
0 2 4 3
2 3 5
3 0
7 2 3
3 0 2 1 3 0 1
7 1 4
4 4 3 0 2 4 2
5 2 3
1 2 3 2 2
outputCopy
Yes
No
Yes
Yes
Yes
No
No
Note
In the following 𝑠 denotes the shore, 𝑖 denotes the island, 𝑥 denotes distance from Koa to the shore, the underline denotes the position of Koa, and values in the array below denote current depths, affected by tide, at 1,2,…,𝑛 meters from the shore.

In test case 1 we have 𝑛=2,𝑘=1,𝑙=1,𝑝=[0,1].

Koa wants to go from shore (at 𝑥=0) to the island (at 𝑥=3). Let’s describe a possible solution:

Initially at 𝑡=0 the beach looks like this: [𝑠⎯⎯,1,0,𝑖].
At 𝑡=0 if Koa would decide to swim to 𝑥=1, beach would look like: [𝑠,2⎯⎯,1,𝑖] at 𝑡=1, since 2>1 she would drown. So Koa waits 1 second instead and beach looks like [𝑠⎯⎯,2,1,𝑖] at 𝑡=1.
At 𝑡=1 Koa swims to 𝑥=1, beach looks like [𝑠,1⎯⎯,0,𝑖] at 𝑡=2. Koa doesn’t drown because 1≤1.
At 𝑡=2 Koa swims to 𝑥=2, beach looks like [𝑠,2,1⎯⎯,𝑖] at 𝑡=3. Koa doesn’t drown because 1≤1.
At 𝑡=3 Koa swims to 𝑥=3, beach looks like [𝑠,1,0,𝑖⎯] at 𝑡=4.
At 𝑡=4 Koa is at 𝑥=3 and she made it!
We can show that in test case 2 Koa can’t get to the island.

题意:
n个点,每个点在时间t的深度为 d [ i ] + p [ t m o d    2 k ] d[i]+p[t\mod2k] d[i]+p[tmod2k]
p数组为 [ 0 , 1 , 2 , . . , k , k − 1 , k − 2...2 , 1 ] [0,1,2,..,k,k-1,k-2...2,1] [0,1,2,..,k,k1,k2...2,1]
从一个点到另一个点的时间花费为1,你可以在一个点呆任意时间。
要求任意时刻都不能出现深度大于 L L L

思路:
冷静分析了一波,发现其实可写。

暴力的话,我们维护每个点能多少个时间能走到即可,就可以得到能否走到下一个点。

B2数据范围大,我们维护的时间肯定不能多。
从前一个点走到下一个点,肯定希望附加给下一个点的额外深度越小越好。
所以我们只需要维护到达每个点在 [ 0 , k − 1 ] [0,k-1] [0,k1]内的最短时间与 [ k , 2 ∗ k − 1 ] [k,2*k-1] [k,2k1]内的最短时间。

然后直接DP转移就好了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

typedef long long ll;
const int maxn = 3e5 + 7;
const int INF = 2e9;
int dp[maxn][2];//到达i点的最小时间最大时间
int a[maxn];
int n,k,l;

int get(int x) {
    x %= 2 * k;
    if(x <= k - 1) {
        return x;
    } else {
        x -= k - 1;
        return k - x + 1;
    }
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        scanf("%d%d%d",&n,&k,&l);
        int flag = 1;
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            if(a[i] > l) {
                flag = 0;
            }
        }
        dp[0][0] = 0;dp[0][1] = k;
        for(int i = 1;i <= n;i++) {
            int mi = dp[i - 1][0],mx = dp[i - 1][1];
            int MI = INF,MX = INF;
            int ok = 0;
            if(mi != INF) {
                if(a[i] + get(mi + 1) <= l) {
                    ok++;
                    if(mi == k - 1) {
                        MX = min(MX,k);
                    } else {
                        MI = min(MI,mi + 1);
                    }
                }
            }
            
            if(mx != INF) {
                int num = 2 * k - (l - a[i]); //最低位置
                ok++;
                if(mx == 2 * k - 1 || num == 2 * k) {
                    MI = min(MI,0);
                } else {
                    MX = min(MX,max(num,mx + 1));
                }
            }
            
            if(ok == 0) {
                flag = 0;
                break;
            } else {
                if(MX != INF && a[i] + get(MX) <= l) {
                    MI = 0;
                }
                if(a[i] + k <= l) {
                    MI = 0;
                    MX = k;
                }
            }
            dp[i][0] = MI;dp[i][1] = MX;
        }
        
        if(!flag) {
            printf("NO\n");
        } else {
            printf("YES\n");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值