[APIO2015] Sculpture in Bali --- Greed + Enumeration

[APIO2015] Sculptures in Bali 

Topic description

There are many sculptures on the roads of Bali, Indonesia, let's focus on one of its main roads.

There are a total of \(N\) sculptures on this main road. For the sake of convenience, we number these sculptures from  1  to \(N\) consecutively, and the age of the \(i\) sculpture is\ (Y_{i}\) years.

In order to make the environment of this road more beautiful, the government wants to divide these sculptures into groups, and by planting some trees between the groups, to attract more tourists to Bali.

Here are the rules for grouping sculptures:

These sculptures must be divided into exactly \(X\) groups, where \(A<=X<=B\) , each group must contain at least one sculpture, and each sculpture must also belong to one and only one group.

All sculptures in the same group must be located on a continuous stretch of the road.

When sculptures are grouped, for each group, we first calculate the sum of the ages of all sculptures in that group.

Compute all ages and bitwise OR the result. We call this value the final gracefulness of this grouping.

What is the smallest final gracefulness that the government can get?

 

data range:

 

or the largest value---) bitwise greedy

In order to ensure the minimum, greedy from high to low (although the maximum is the same...)

So how do you determine the smallest answer?

Note that high-order greedy results need to be preserved (high-order must be better).

Therefore, maintaining \(dp(i,j)\) means enumerating to the \(i\)th bit, which is divided into \(j\) blocks. Can the current bit be 0 while satisfying the high-order greed.

If one of \(dp(n,A)...dp(n,B)\) is satisfied, then the current bit can be 0, which is counted as the high bit.

How to transfer?

Just enumerate, enumerate all the intervals to transfer, it takes \(n^{2}*B\) time to determine whether a bit can be 0

Total time required\(O(\log n *B*n^{2})\)

 

It can be found that the last point cannot be missed.

But \(A=1\) is very conspicuous, what's the use?

This tells us that there is no next session, only the previous session.

Therefore, only how many blocks are required to make the current bit 0 while satisfying the high-bit greed can also be judged.

The complexity can be reduced to:

\(O(\log n * n ^{2})\)

 

#include <cstdio>
#include <cstring>
#define ll long long
#define ri register int
using namespace std;

char RR[34567], *S = RR, *T = RR + 30000;
inline char gc() {
    if(S == T) fread(RR, 1, 30000, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') {
        if(c == '-') w = -1;
        c = gc();
    }
    while(c >= '0' && c <= '9') {
        p = p * 10 + c - '0';
        c = gc();
    }
    return p;
}

template <typename re>
inline void upmin(re &a, re b) { if(a > b) a = b; }

int n, A, B;
ll ans, sum[2005], bit[100];
bool dp[105][105];
int f[2005];

void Solve1() {
    for(ri p = 41; p; p --) {
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        for(ri i = 1; i <= n; i ++)
        for(ri j = 1; j <= i; j ++)
        for(ri k = j - 1; k <= i - 1; k ++)
        if(dp[k][j - 1]) {
            ll pp = sum[i] - sum[k];
            if(((pp >> p) | ans) == ans)
            if((pp & bit[p - 1]) == 0) dp[i][j] = 1;
        }
        ans <<= 1; ans |= 1;
        for(ri i = A; i <= B; i ++) 
        if(dp[n][i]) { ans ^= 1; break; }
    }
    printf("%lld\n", ans);
}

void Solve2() {
    for(ri p = 41; p; p --) {
        for(ri i = 1; i <= n; i ++) f[i] = 3000;
        for(ri i = 1; i <= n; i ++)
        for(ri j = 0; j <= i - 1; j ++) {
            ll pp = sum[i] - sum[j];
            if(((pp >> p) | ans) == ans)
            if((pp & bit[p - 1]) == 0) upmin(f[i], f[j] + 1);
        }
        ans <<= 1;
        if(f[n] > B) ans |= 1;
    }
    printf("%lld\n", ans);
}

int main() {
    for(ri i = 0; i <= 58; i ++) bit[i] = 1LL << i;
    n = read(); A = read(); B = read();
    for(ri i = 1; i <= n; i ++) sum[i] = sum[i - 1] + read();
    if(A == 1) Solve2(); 
    else Solve1();
    return 0;
}
Aha!

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325311770&siteId=291194637