Logue P4563 [JXOI2018] guard (dp)

Keywords: C++

meaning of the title

Title Link

Sol

A very interesting topic.

We set \ (f[l][r] \) to represent the answer of interval \ ([l,r] \).

Obviously there must be a bodyguard at \ (r \)

At the same time, it is not difficult to observe a property: take \ ([1, n] \) for example, if a certain interval it cannot observe is \ ([l_k, r_k] \), then \ (r_k \) and \ (r_k + 1 \) must have a bodyguard, and the contribution of each interval is independent.

In this way, we can preprocess whether any two points can be seen (directly record a visible position and compare the slope).

Then directly enumerate \ (r \), and constantly move \ (l \) to the left to update the answer, so as to ensure that the interval in the middle of the update is calculated, and can be directly prefixed and optimized

Complexity \ (O(n^2) \)

#include<bits/stdc++.h>
#define Fin(x) freopen(#x".in", "r", stdin);
using namespace std;
const int MAXN = 5001;
template<typename A, typename B> inline bool chmax(A &x, B y) {return x < y ? x = y, 1 : 0;}
template<typename A, typename B> inline bool chmin(A &x, B y) {return x > y ? x = y, 1 : 0;}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, f[MAXN][MAXN];
double a[MAXN];
bool can[MAXN][MAXN];
int main() {
    //Fin(a);
    N = read();
    for(int i = 1; i <= N; i++) a[i] = read();
    for(int i = 1; i <= N; i++) {
        for(int j = i - 1, las = -1; j; j--) 
            if((las == -1) || (1ll * (a[i] - a[las]) * (i - j) > 1ll * (a[i] - a[j]) * (i - las))) 
                can[i][j] = can[j][i] =1, las = j;
    }
    int ans= 0;
    for(int i = 1; i <= N; i++) {
        int s = 1, las = 0;
        for(int j = i; j; j--) {
            if(can[j][i]) {
                if(!can[j + 1][i]) s += min(f[j + 1][las], f[j + 1][las + 1]);
                f[j][i] = s;
            } else {
                if(can[j + 1][i]) las = j;
                f[j][i] = s + min(f[j][las], f[j][las + 1]);
            }
            ans ^= f[j][i];
        //  printf("%d ", f[j][i]);
        }
    //  puts("");
    }
    cout << ans;
    return 0;
}

Posted by GreyBoy on Sat, 30 Nov 2019 13:00:49 -0800