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;
}