2019/10/3 CSP-S simulation test

Ex T1

Meaning of the questions:

Seeking \ (1 - n \) are arranged in reverse order of the number \ (K \) number of arrayed

SOL:

We know that is definitely not the exclusion \ (O (n!) \ ) Algorithm
Consider \ (dp \) , now has \ (n-1 \) answers, and consider adding a new number in reverse order to produce much new
set \ (dp [i] [j ] \) represents \ (1 -i \) arrayed \ (J \) number of inversions pairs, regardless of the number of new added inserted where many reverse number will increase
with a \ [dp [i] [j ] = \ sum \ limits ^ {min (i - 1, j)} _ k
dp [i - 1] [j - k] \] seem strange, that alterations shaped \ [dp [i] [j ] = \ sum \ limits ^ j_ {max (0, j - i + 1} dp [i
- 1] [k] \] complexity \ (O (n-2 * K ^) \) , \ (O (not run) \)
consider a prefix and optimization, like "I to long high "and" \ (Making the Grade \) "in the same
due to the \ (K \) upper bound with \ (J \) varies changes, consider the accumulation at the time of the cycle \ (dp [i - 1 ] [J] \) to a variable, and then assigned \ (dp [i] [j
] \) Note that \ (K \) of lower bound\ (j - i + 1 \ geq 0 \) when the change will occur, remember to subtract pay more

#include<bits/stdc++.h>
#define N (1000 + 10)
using namespace std;
int T;
int n, k, sum, f[N][N];
const int mod = 10000;
int main() {
    scanf("%d", &T);
    f[1][0] = 1;
    while (T--) {
        scanf("%d%d", &n, &k);
        if (f[n][k]) {printf("%d\n", f[n][k]); continue;}
        for (register int i = 2; i <= n; ++i) {
            sum = 0;
            for (register int j = 0; j <= k; ++j) {
                sum += f[i - 1][j] % mod;
                f[i][j] = sum % mod;
                if (j - i + 1 >= 0) sum -= f[i - 1][j - i + 1] % mod;
            }
        }
        printf("%d\n", f[n][k]);
    }
    return 0;
}

T2 Beautiful

Meaning of the questions:

Define the value of a number of \ (V_I \) to use it as the median interval maximum length, \ (Q \) queries interrogation interval \ ([l, r] \ ) the maximum within the \ (V_I \) , when compared to the original size by the number of the first key value, the second key labeled
\ (n \ leq 2000, Q \ leq 100000 \)

SOL:

See \ (n \) is very small, can not think about how to operate it

Consider \ (O (n) \) enumerate every number, and then expand to the right and left, respectively, recording a variable \ (S \) , encountered bigger than it would \ (- S \) , or \ ( S ++ \) , then for each \ (S \) is a record value farthest position, and finally take the pieces together to get the maximum length \ (v_i \)
then just how to do something \ (RMQ \) to

#include<bits/stdc++.h>
#define N (100000 + 10)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
    return cnt * f;
}
int n, Q, l, r;
int S1[N], S2[N];
int a[N], b[N];
int t[N];
int A[N];
struct node {
    int l, r;
    int gmax;
    #define l(p) tree[p].l
    #define r(p) tree[p].r
    #define gmax(p) tree[p].gmax
}tree[N << 2];


void pushup(int p) {
    gmax(p) = max(gmax(p << 1), gmax(p << 1 | 1));
}

void build(int p, int l, int r) {
    l(p) = l, r(p) = r;
    if (l == r) {gmax(p) = A[l]; return;}
    int mid = (l + r) >> 1;
    build (p << 1, l, mid);
    build (p << 1 | 1, mid + 1, r);
    pushup(p);
}

long long query(int p, int l, int r) {
    if (l <= l(p) && r >= r(p)) return gmax(p);
    int mid = (l(p) + r(p)) >> 1;
    long long ans = -1;
    if (l <= mid) ans = max(ans, query(p << 1, l, r));
    if (r > mid) ans = max(ans, query(p << 1 | 1, l, r));
    return ans;
}

int main() {
    n = read(); for (register int i = 1; i <= n; ++i) a[i] = read();
    for (register int i = 1; i <= n; ++i) {
        int tmp = 0;
        memset(S1, 255, sizeof(S1));
        memset(S2, 255, sizeof(S2));
        S1[n] = S2[n] = 0;
        for (register int j = i - 1; j >= 1; --j) {
            if (a[j] > a[i]) ++tmp; if (a[j] <= a[i]) --tmp;
            S1[tmp + n] = i - j;
        }
        tmp = 0;
        for (register int j = i + 1; j <= n; ++j) {
            if (a[j] >= a[i]) ++tmp; if (a[j] < a[i]) --tmp;
            S2[tmp + n] = j - i;
        }
        for (register int j = 1 - i; j <= i - 1; ++j) if (S1[n + j] >= 0 && S2[n - j] >= 0) A[i] = max(A[i], S1[n + j] + 1 + S2[n - j]);
    } Q = read();
//  for (register int i = 1; i <= n; ++i) cout<<A[i]<<" ";return 0;
    build (1, 1, n);
    while (Q--) {
        l = read(), r = read();
        printf("%lld\n", query(1, l, r));
    }
    return 0;
}

T3 Subset

Meaning of the questions:

Maintains a set of \ (A \) , support the insertion of a delete query (a_i \ & S = a_i \ ) \ number, \ (a_i \ in A \) , the operation \ (2E5 \) , digital size \ (2 ^ {16 } \)

SOL:

Fantastic idea
to consider binary, the number of split into two, recorded \ (s [a] [b ] \) represents the first eight bits are \ (A \) , after eight is \ (B \) subset number
for \ (the Add \) and \ (del \) given \ (B \) enumeration \ (a \) update
for \ (CNT \) operations in a given \ (a \) enumeration \ (B \) update
the balance between the complexity of the query and modify the time complexity is optimized \ (O (n * 2 ^ 8) \)

#include<bits/stdc++.h>
#define N ((1 << 8) + 5)
using namespace std;
int Q, x;
char ope[5];
int s[N][N];
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
    return cnt * f;
}
void add(int x) {
    int a = x >> 8, b = x - (a << 8);
    for (register int i = 0; i < (1 << 8); ++i) if ((i & a) == a) s[i][b]++;
}
void del(int x) {
    int a = x >> 8, b = x - (a << 8);
    for (register int i = 0; i < (1 << 8); ++i) if ((i & a) == a) s[i][b]--;
}
int query(int x) {
    int ans = 0, a = x >> 8, b = x - (a << 8);
    for (register int i = 0; i < (1 << 8); ++i) if ((i & b) == i) ans += s[a][i];
    return ans;
}
int main() {
    Q = read();
    while (Q--) {
        scanf("%s", ope + 1); x = read();
        if (ope[1] == 'a') add(x);
        if (ope[1] == 'd') del(x);
        if (ope[1] == 'c') printf("%d\n", query(x));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/kma093/p/11621761.html