Logue P4424 [HNOI/AHOI2018] treasure hunt game (thinking problem)

meaning of the title

Title Link

Sol

Fairy question Orz

Orz zbq searches 70..

Consider the nature of "and" and "or"

\(0 \& 0 = 0, 1 \& 0 = 0\)

\(0 \mid 1 = 1, 1 \mid 1 = 1\)

That is to say, after a certain number \ (\ & 0 \), no matter what it was before, the current value changes to \ (0 \)

After a certain number \ (\ mid 1 \), no matter what it was before, the current value changes to \ (1 \)

Continue to consider

\(0 \& 1 = 0, 1 \& 1 = 1\)

\(0 \mid 0 = 0, 1 \mid 0 = 1\)

At this time, we regard \ (\ & \) as 1, \ (\ mid \) as \ (0 \)

So for the above two formulas, it can be seen that if a number is the same as the previous operator, the previous value will not change

At this time, consider how to calculate the answer. For each query, if a bit is \ (1 \)

Then we take the number in each column and the operators before it as some sequences. Obviously, this sequence should meet the requirement that the last \ (\ mid 1 \) should be after \ (\ & 0 \)

So these two sequences should look like this:

\(101010 \dots 0 \dots 1\)

\(101010 \dots 1 \dots 0\)

We will be surprised to find that the first formula must be larger than the second one. Similarly, if the location of the query is \ (0 \), the first formula should be smaller than the second one

Because \ (0 / 1 \) of the second formula can be taken arbitrarily. Then the answer should be \ (min_1 - max_0 \), \ (min_1 \) means that the value on the query position is the minimum value of the corresponding column of \ (1 \) (the first row of each column is the lowest).

The complexity is \ (O(nmq) \)

In fact, each time we ask about the size of each column, we can arrange the order according to the size of the string first (to figure out the sa and rak arrays in the suffix array), so that we only need to calculate the answers of two strings each time we ask

Complexity: \ (O(mn\log m + mq) \)

#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 5e5 + 10, INF = 1e9 + 7, mod = 1000000007;
template<typename A, typename B> inline void chmax(A &x, B y) {
    x = x > y ? x : y;
}
template<typename A, typename B> inline void chmin(A &x, B y) {
    x = x < y ? x : y;
}
template<typename A, typename B> inline void add2(A &x, B y) {
    x = (x + y >= mod ? x + y - mod : x + y);
}
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, M, Q, v[MAXN], rak[MAXN], po2[MAXN], sa[MAXN], val[MAXN];
char a[1002][5002], q[5001];
int comp(const int &x, const int &y) {
    for(int i = N; i >= 1; i--)
        if(a[i][x] == '0' && a[i][y] == '1') return 1;
        else if(a[i][x] == '1' && a[i][y] == '0') return 0;
    return 0;
}
int trans(int id) {
    int ans = 0;
    for(int i = N; i >= 1; i--) 
        if(a[i][id] == '1') add2(ans, po2[i - 1]);
    return ans;
}
int main() {
//  freopen("a.in", "r", stdin);
    N = read(); M = read(); Q = read(); po2[0] = 1;
    for(int i = 1; i <= N; i++) scanf("%s", a[i] + 1), po2[i] = (po2[i - 1] * 2) % mod;
    for(int i = 1; i <= N; i++) a[i][M + 1] = '1', a[i][0]= '0'; 
    for(int i = 1; i <= M + 1; i++) sa[i] = i;
    sort(sa + 1, sa + M + 2, comp);
    for(int i = 1; i <= M + 1; i++) rak[sa[i]] = i;
    for(int i = 1; i <= M + 1; i++) val[i] = trans(i); val[M + 1]++;//No + + is 1 less than the answer. If it's added, it's too inexplicable... 
    for(int i = 1; i <= Q; i++) {
        scanf("%s", q + 1);
        int r = M + 1, l = 0;
        for(int j = 1; j <= M; j++) 
            if(q[j] == '1') chmin(r, rak[j]);
            else chmax(l, rak[j]);
        if(l > r) puts("0");
        else cout << (val[sa[r]] - val[sa[l]] + mod) % mod << '\n';
    }
    return 0;
}
/*
3
0 1 1
5 7 3
*/

Tags: C++ less

Posted on Mon, 02 Dec 2019 09:11:12 -0500 by jimthunderbird