NOIP模拟测试11
昨天颓了一天,今天考试没干劲。
最主要问题:无法深入思考,只会打暴力。
Problem A: string
感觉和HEOI2016排序差不多,但刚了半小时没想出来,打了sort的40暴力。
正解确实和那题差不多,线段树存每个区间每种颜色的数目,每次修改开个cnt数组查询修改区间每种颜色的数目,从小到大的把数目大小的区间颜色都改了。
这个思路还是蛮好理解的。速码。
TLE。50。
#include <bits/stdc++.h>
const int N = 100000 + 233;
int n, m, sum[N << 2][30], L[N << 2], R[N << 2], lazy[N << 2];
char s[N];
void build(int p, int l, int r) {
L[p] = l, R[p] = r;
if (l == r) return (void) (sum[p][s[l] - 'a' + 1] = 1);
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
for (int i = 1; i <= 26; i++)
sum[p][i] = sum[p << 1][i] + sum[p << 1 | 1][i];
}
inline void pushdown(int p) {
if (!lazy[p]) return;
for (int i = (p << 1); i <= (p << 1 | 1); i++) {
for (int j = 1; j <= 26; j++) sum[i][j] = 0;
sum[i][lazy[p]] = R[i] - L[i] + 1, lazy[i] = lazy[p];
}
lazy[p] = 0;
}
void change(int p, int l, int r, int k) {
if (L[p] >= l && R[p] <= r) {
for (int i = 1; i <= 26; i++) sum[p][i] = 0;
sum[p][k] = R[p] - L[p] + 1;
lazy[p] = k;
return;
}
pushdown(p);
int mid = (L[p] + R[p]) >> 1;
if (l <= mid) change(p << 1, l, r, k);
if (r > mid) change(p << 1 | 1, l, r, k);
for (int i = 1; i <= 26; i++)
sum[p][i] = sum[p << 1][i] + sum[p << 1 | 1][i];
}
int ask(int p, int l, int r, int k) {
if (L[p] >= l && R[p] <= r) return sum[p][k];
pushdown(p);
int mid = (L[p] + R[p]) >> 1, ret = 0;
if (l <= mid) ret += ask(p << 1, l, r, k);
if (r > mid) ret += ask(p << 1 | 1, l, r, k);
return ret;
}
void print(int p, int l, int r) {
if (l == r) {
for (int i = 1; i <= 26; i++)
if (sum[p][i]) return (void) printf("%c", i + 'a' - 1);
return;
}
pushdown(p);
int mid = (l + r) >> 1;
print(p << 1, l, mid), print(p << 1 | 1, mid + 1, r);
}
signed main() {
scanf("%d%d%s", &n, &m, s + 1);
build(1, 1, n);
for (int i = 1, l, r, x; i <= m; i++) {
scanf("%d%d%d", &l, &r, &x);
int cnt[30] = {}, lst = l;
for (int j = 1; j <= 26; j++)
cnt[j] = ask(1, l, r, j);
if (x == 1)
for (int j = 1; j <= 26; j++)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
else
for (int j = 26; j >= 1; j--)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
}
print(1, 1, n);
puts("");
return 0;
}
我草了,这题卡常!!!!
开始卡常:数组紧贴着开,线段树开3倍也可以。
60。
#include <bits/stdc++.h>
const int N = 100000 + 233;
int n, m, sum[N * 3][27], L[N * 3], R[N * 3], lazy[N * 3], cnt[27];
char s[N];
inline int read() {
int a = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a;
}
void build(int p, int l, int r) {
L[p] = l, R[p] = r;
if (l == r) return (void) (sum[p][s[l] - 'a' + 1] = 1);
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
for (int i = 1; i <= 26; i++)
sum[p][i] = sum[p << 1][i] + sum[p << 1 | 1][i];
}
inline void pushdown(int p) {
if (!lazy[p]) return;
for (int i = (p << 1); i <= (p << 1 | 1); i++) {
for (int j = 1; j <= 26; j++) sum[i][j] = 0;
sum[i][lazy[p]] = R[i] - L[i] + 1, lazy[i] = lazy[p];
}
lazy[p] = 0;
}
void change(int p, int l, int r, int k) {
if (L[p] >= l && R[p] <= r) {
for (int i = 1; i <= 26; i++) sum[p][i] = 0;
sum[p][k] = R[p] - L[p] + 1, lazy[p] = k;
return;
}
pushdown(p);
int mid = (L[p] + R[p]) >> 1;
if (l <= mid) change(p << 1, l, r, k);
if (r > mid) change(p << 1 | 1, l, r, k);
for (int i = 1; i <= 26; i++)
sum[p][i] = sum[p << 1][i] + sum[p << 1 | 1][i];
}
void ask(int p, int l, int r) {
if (L[p] >= l && R[p] <= r){
for (int i = 1; i <= 26; i++)
cnt[i] += sum[p][i];
return;
}
pushdown(p);
int mid = (L[p] + R[p]) >> 1;
if (l <= mid) ask(p << 1, l, r);
if (r > mid) ask(p << 1 | 1, l, r);
}
void print(int p, int l, int r) {
if (l == r) {
for (int i = 1; i <= 26; i++)
if (sum[p][i]) return (void) putchar(i + 'a' - 1);
return;
}
pushdown(p);
int mid = (l + r) >> 1;
print(p << 1, l, mid), print(p << 1 | 1, mid + 1, r);
}
signed main() {
n = read(), m = read();
scanf("%s", s + 1);
build(1, 1, n);
for (int i = 1, l, r, x; i <= m; i++) {
l = read(), r = read(), x = read();
int lst = l;
ask(1, l, r);
if (x == 1)
for (int j = 1; j <= 26; j++)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
else
for (int j = 26; j >= 1; j--)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
for (int i = 1; i <= 26; i++) cnt[i] = 0;
}
print(1, 1, n);
puts("");
return 0;
}
这时cwy很郁闷,突然想起WC的挑战,N方也能过百万,秘籍:循环展开。
疯狂展开,同时,ask不再返回,把cnt开成全局直接修改。change时候不再循环1-26,cnt不为0再进入change函数,避免传参的时间损失,pushdown直接写到函数里。
改了好久,终于A了。
AC代码:(344行)
#include <bits/stdc++.h>
const int N = 100000 + 1;
int n, m, sum[N * 3][27], L[N * 3], R[N * 3], lazy[N * 3], cnt[27];
char s[N];
inline int read() {
int a = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a;
}
void build(int p, int l, int r) {
L[p] = l, R[p] = r;
if (l == r) return (void) (sum[p][s[l] - 'a' + 1] = 1);
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
sum[p][1] = sum[p << 1][1] + sum[p << 1 | 1][1];
sum[p][2] = sum[p << 1][2] + sum[p << 1 | 1][2];
sum[p][3] = sum[p << 1][3] + sum[p << 1 | 1][3];
sum[p][4] = sum[p << 1][4] + sum[p << 1 | 1][4];
sum[p][5] = sum[p << 1][5] + sum[p << 1 | 1][5];
sum[p][6] = sum[p << 1][6] + sum[p << 1 | 1][6];
sum[p][7] = sum[p << 1][7] + sum[p << 1 | 1][7];
sum[p][8] = sum[p << 1][8] + sum[p << 1 | 1][8];
sum[p][9] = sum[p << 1][9] + sum[p << 1 | 1][9];
sum[p][10] = sum[p << 1][10] + sum[p << 1 | 1][10];
sum[p][11] = sum[p << 1][11] + sum[p << 1 | 1][11];
sum[p][12] = sum[p << 1][12] + sum[p << 1 | 1][12];
sum[p][13] = sum[p << 1][13] + sum[p << 1 | 1][13];
sum[p][14] = sum[p << 1][14] + sum[p << 1 | 1][14];
sum[p][15] = sum[p << 1][15] + sum[p << 1 | 1][15];
sum[p][16] = sum[p << 1][16] + sum[p << 1 | 1][16];
sum[p][17] = sum[p << 1][17] + sum[p << 1 | 1][17];
sum[p][18] = sum[p << 1][18] + sum[p << 1 | 1][18];
sum[p][19] = sum[p << 1][19] + sum[p << 1 | 1][19];
sum[p][20] = sum[p << 1][20] + sum[p << 1 | 1][20];
sum[p][21] = sum[p << 1][21] + sum[p << 1 | 1][21];
sum[p][22] = sum[p << 1][22] + sum[p << 1 | 1][22];
sum[p][23] = sum[p << 1][23] + sum[p << 1 | 1][23];
sum[p][24] = sum[p << 1][24] + sum[p << 1 | 1][24];
sum[p][25] = sum[p << 1][25] + sum[p << 1 | 1][25];
sum[p][26] = sum[p << 1][26] + sum[p << 1 | 1][26];
}
void change(int p, int l, int r, int k) {
if (L[p] >= l && R[p] <= r) {
sum[p][1] = 0;
sum[p][2] = 0;
sum[p][3] = 0;
sum[p][4] = 0;
sum[p][5] = 0;
sum[p][6] = 0;
sum[p][7] = 0;
sum[p][8] = 0;
sum[p][9] = 0;
sum[p][10] = 0;
sum[p][11] = 0;
sum[p][12] = 0;
sum[p][13] = 0;
sum[p][14] = 0;
sum[p][15] = 0;
sum[p][16] = 0;
sum[p][17] = 0;
sum[p][18] = 0;
sum[p][19] = 0;
sum[p][20] = 0;
sum[p][21] = 0;
sum[p][22] = 0;
sum[p][23] = 0;
sum[p][24] = 0;
sum[p][25] = 0;
sum[p][26] = 0;
sum[p][k] = R[p] - L[p] + 1, lazy[p] = k;
return;
}
if (lazy[p]) {
sum[p << 1][1] = 0;
sum[p << 1][2] = 0;
sum[p << 1][3] = 0;
sum[p << 1][4] = 0;
sum[p << 1][5] = 0;
sum[p << 1][6] = 0;
sum[p << 1][7] = 0;
sum[p << 1][8] = 0;
sum[p << 1][9] = 0;
sum[p << 1][10] = 0;
sum[p << 1][11] = 0;
sum[p << 1][12] = 0;
sum[p << 1][13] = 0;
sum[p << 1][14] = 0;
sum[p << 1][15] = 0;
sum[p << 1][16] = 0;
sum[p << 1][17] = 0;
sum[p << 1][18] = 0;
sum[p << 1][19] = 0;
sum[p << 1][20] = 0;
sum[p << 1][21] = 0;
sum[p << 1][22] = 0;
sum[p << 1][23] = 0;
sum[p << 1][24] = 0;
sum[p << 1][25] = 0;
sum[p << 1][26] = 0;
sum[p << 1][lazy[p]] = R[p << 1] - L[p << 1] + 1, lazy[p << 1] = lazy[p];
sum[p << 1 | 1][1] = 0;
sum[p << 1 | 1][2] = 0;
sum[p << 1 | 1][3] = 0;
sum[p << 1 | 1][4] = 0;
sum[p << 1 | 1][5] = 0;
sum[p << 1 | 1][6] = 0;
sum[p << 1 | 1][7] = 0;
sum[p << 1 | 1][8] = 0;
sum[p << 1 | 1][9] = 0;
sum[p << 1 | 1][10] = 0;
sum[p << 1 | 1][11] = 0;
sum[p << 1 | 1][12] = 0;
sum[p << 1 | 1][13] = 0;
sum[p << 1 | 1][14] = 0;
sum[p << 1 | 1][15] = 0;
sum[p << 1 | 1][16] = 0;
sum[p << 1 | 1][17] = 0;
sum[p << 1 | 1][18] = 0;
sum[p << 1 | 1][19] = 0;
sum[p << 1 | 1][20] = 0;
sum[p << 1 | 1][21] = 0;
sum[p << 1 | 1][22] = 0;
sum[p << 1 | 1][23] = 0;
sum[p << 1 | 1][24] = 0;
sum[p << 1 | 1][25] = 0;
sum[p << 1 | 1][26] = 0;
sum[p << 1 | 1][lazy[p]] = R[p << 1 | 1] - L[p << 1 | 1] + 1, lazy[p << 1 | 1] = lazy[p];
lazy[p] = 0;
}
int mid = (L[p] + R[p]) >> 1;
if (l <= mid) change(p << 1, l, r, k);
if (r > mid) change(p << 1 | 1, l, r, k);
sum[p][1] = sum[p << 1][1] + sum[p << 1 | 1][1];
sum[p][2] = sum[p << 1][2] + sum[p << 1 | 1][2];
sum[p][3] = sum[p << 1][3] + sum[p << 1 | 1][3];
sum[p][4] = sum[p << 1][4] + sum[p << 1 | 1][4];
sum[p][5] = sum[p << 1][5] + sum[p << 1 | 1][5];
sum[p][6] = sum[p << 1][6] + sum[p << 1 | 1][6];
sum[p][7] = sum[p << 1][7] + sum[p << 1 | 1][7];
sum[p][8] = sum[p << 1][8] + sum[p << 1 | 1][8];
sum[p][9] = sum[p << 1][9] + sum[p << 1 | 1][9];
sum[p][10] = sum[p << 1][10] + sum[p << 1 | 1][10];
sum[p][11] = sum[p << 1][11] + sum[p << 1 | 1][11];
sum[p][12] = sum[p << 1][12] + sum[p << 1 | 1][12];
sum[p][13] = sum[p << 1][13] + sum[p << 1 | 1][13];
sum[p][14] = sum[p << 1][14] + sum[p << 1 | 1][14];
sum[p][15] = sum[p << 1][15] + sum[p << 1 | 1][15];
sum[p][16] = sum[p << 1][16] + sum[p << 1 | 1][16];
sum[p][17] = sum[p << 1][17] + sum[p << 1 | 1][17];
sum[p][18] = sum[p << 1][18] + sum[p << 1 | 1][18];
sum[p][19] = sum[p << 1][19] + sum[p << 1 | 1][19];
sum[p][20] = sum[p << 1][20] + sum[p << 1 | 1][20];
sum[p][21] = sum[p << 1][21] + sum[p << 1 | 1][21];
sum[p][22] = sum[p << 1][22] + sum[p << 1 | 1][22];
sum[p][23] = sum[p << 1][23] + sum[p << 1 | 1][23];
sum[p][24] = sum[p << 1][24] + sum[p << 1 | 1][24];
sum[p][25] = sum[p << 1][25] + sum[p << 1 | 1][25];
sum[p][26] = sum[p << 1][26] + sum[p << 1 | 1][26];
}
void ask(int p, int l, int r) {
if (L[p] >= l && R[p] <= r){
cnt[1] += sum[p][1];
cnt[2] += sum[p][2];
cnt[3] += sum[p][3];
cnt[4] += sum[p][4];
cnt[5] += sum[p][5];
cnt[6] += sum[p][6];
cnt[7] += sum[p][7];
cnt[8] += sum[p][8];
cnt[9] += sum[p][9];
cnt[10] += sum[p][10];
cnt[11] += sum[p][11];
cnt[12] += sum[p][12];
cnt[13] += sum[p][13];
cnt[14] += sum[p][14];
cnt[15] += sum[p][15];
cnt[16] += sum[p][16];
cnt[17] += sum[p][17];
cnt[18] += sum[p][18];
cnt[19] += sum[p][19];
cnt[20] += sum[p][20];
cnt[21] += sum[p][21];
cnt[22] += sum[p][22];
cnt[23] += sum[p][23];
cnt[24] += sum[p][24];
cnt[25] += sum[p][25];
cnt[26] += sum[p][26];
return;
}
if (lazy[p]) {
sum[p << 1][1] = 0;
sum[p << 1][2] = 0;
sum[p << 1][3] = 0;
sum[p << 1][4] = 0;
sum[p << 1][5] = 0;
sum[p << 1][6] = 0;
sum[p << 1][7] = 0;
sum[p << 1][8] = 0;
sum[p << 1][9] = 0;
sum[p << 1][10] = 0;
sum[p << 1][11] = 0;
sum[p << 1][12] = 0;
sum[p << 1][13] = 0;
sum[p << 1][14] = 0;
sum[p << 1][15] = 0;
sum[p << 1][16] = 0;
sum[p << 1][17] = 0;
sum[p << 1][18] = 0;
sum[p << 1][19] = 0;
sum[p << 1][20] = 0;
sum[p << 1][21] = 0;
sum[p << 1][22] = 0;
sum[p << 1][23] = 0;
sum[p << 1][24] = 0;
sum[p << 1][25] = 0;
sum[p << 1][26] = 0;
sum[p << 1][lazy[p]] = R[p << 1] - L[p << 1] + 1, lazy[p << 1] = lazy[p];
sum[p << 1 | 1][1] = 0;
sum[p << 1 | 1][2] = 0;
sum[p << 1 | 1][3] = 0;
sum[p << 1 | 1][4] = 0;
sum[p << 1 | 1][5] = 0;
sum[p << 1 | 1][6] = 0;
sum[p << 1 | 1][7] = 0;
sum[p << 1 | 1][8] = 0;
sum[p << 1 | 1][9] = 0;
sum[p << 1 | 1][10] = 0;
sum[p << 1 | 1][11] = 0;
sum[p << 1 | 1][12] = 0;
sum[p << 1 | 1][13] = 0;
sum[p << 1 | 1][14] = 0;
sum[p << 1 | 1][15] = 0;
sum[p << 1 | 1][16] = 0;
sum[p << 1 | 1][17] = 0;
sum[p << 1 | 1][18] = 0;
sum[p << 1 | 1][19] = 0;
sum[p << 1 | 1][20] = 0;
sum[p << 1 | 1][21] = 0;
sum[p << 1 | 1][22] = 0;
sum[p << 1 | 1][23] = 0;
sum[p << 1 | 1][24] = 0;
sum[p << 1 | 1][25] = 0;
sum[p << 1 | 1][26] = 0;
sum[p << 1 | 1][lazy[p]] = R[p << 1 | 1] - L[p << 1 | 1] + 1, lazy[p << 1 | 1] = lazy[p];
lazy[p] = 0;
}
int mid = (L[p] + R[p]) >> 1;
if (l <= mid) ask(p << 1, l, r);
if (r > mid) ask(p << 1 | 1, l, r);
}
void print(int p, int l, int r) {
if (l == r) {
if (sum[p][1]) return (void) putchar('a');
if (sum[p][2]) return (void) putchar('b');
if (sum[p][3]) return (void) putchar('c');
if (sum[p][4]) return (void) putchar('d');
if (sum[p][5]) return (void) putchar('e');
if (sum[p][6]) return (void) putchar('f');
if (sum[p][7]) return (void) putchar('g');
if (sum[p][8]) return (void) putchar('h');
if (sum[p][9]) return (void) putchar('i');
if (sum[p][10]) return (void) putchar('j');
if (sum[p][11]) return (void) putchar('k');
if (sum[p][12]) return (void) putchar('l');
if (sum[p][13]) return (void) putchar('m');
if (sum[p][14]) return (void) putchar('n');
if (sum[p][15]) return (void) putchar('o');
if (sum[p][16]) return (void) putchar('p');
if (sum[p][17]) return (void) putchar('q');
if (sum[p][18]) return (void) putchar('r');
if (sum[p][19]) return (void) putchar('s');
if (sum[p][20]) return (void) putchar('t');
if (sum[p][21]) return (void) putchar('u');
if (sum[p][22]) return (void) putchar('v');
if (sum[p][23]) return (void) putchar('w');
if (sum[p][24]) return (void) putchar('x');
if (sum[p][25]) return (void) putchar('y');
if (sum[p][26]) return (void) putchar('z');
return;
}
if (lazy[p]) {
for (int i = L[p]; i <= R[p]; i++)
putchar('a' + lazy[p] - 1);
return;
}
int mid = (l + r) >> 1;
print(p << 1, l, mid), print(p << 1 | 1, mid + 1, r);
}
signed main() {
n = read(), m = read();
scanf("%s", s + 1);
build(1, 1, n);
for (int i = 1, l, r, x; i <= m; i++) {
l = read(), r = read(), x = read();
int lst = l;
ask(1, l, r);
if (x == 1) {
for (int j = 1; j <= 26 && lst <= n; j++)
if (cnt[j] != 0)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
} else {
for (int j = 26; j >= 1 && lst <= n; j--)
if (cnt[j] != 0)
change(1, lst, lst + cnt[j] - 1, j), lst += cnt[j];
}
cnt[1] = 0;
cnt[2] = 0;
cnt[3] = 0;
cnt[4] = 0;
cnt[5] = 0;
cnt[6] = 0;
cnt[7] = 0;
cnt[8] = 0;
cnt[9] = 0;
cnt[10] = 0;
cnt[11] = 0;
cnt[12] = 0;
cnt[13] = 0;
cnt[14] = 0;
cnt[15] = 0;
cnt[16] = 0;
cnt[17] = 0;
cnt[18] = 0;
cnt[19] = 0;
cnt[20] = 0;
cnt[21] = 0;
cnt[22] = 0;
cnt[23] = 0;
cnt[24] = 0;
cnt[25] = 0;
cnt[26] = 0;
}
print(1, 1, n);
puts("");
return 0;
}
Problem B: Matrix
可能我语文好,在题意理解上没啥偏差。不像某GMK
感觉像个DP,但我连状态都不会设计。
怒打20分DFS暴力。
正解...emmm...很奇怪的DP
首先每列只能放一个1,咱们就看列就行了
它的状态是f[i][j]表示前i列有j列在右区间(好奇怪
咱也不知道为啥要这么设计,咱下次再碰上也想不出来
不管他状态为啥这么设计,转移还是能写的(
首先我们要预处理两个数组L[]和R[],表示i这个位置有几个左区间结束,有几个右区间开始。
然后就安置一下在右区间的1。枚举j,有两种情况,放和不放。不放很简单,就是f[i-1][j].放的话有R[i] - (j - 1)个位置,就是f[i - 1][j - 1] * (R[i] - (j - 1))。
再安置左区间。能想到在i-1列结束的左区间每一个都会占用一个1。我们从L[i-1]到L[i]枚举j,这是之前放了几个1。为什么要枚举?在i这个位置结束的左区间可能很多,你都得给他安排。再枚举右区间1的个数k,能放的位置就有i - j - k个。f[i][k] *= (i - j - k).
最后答案f[m][n].
这道题真的怪,再给我出几次我都不一定做的出来。
#include <bits/stdc++.h>
const int N = 3005, P = 998244353;
int n, m, L[N], R[N], f[N][N];
signed main() {
scanf("%d%d", &n, &m);
for (int i = 1, l, r; i <= n; i++)
scanf("%d%d", &l, &r), L[l]++, R[r]++;
for (int i = 1; i <= m; i++)
L[i] += L[i - 1], R[i] += R[i - 1];
f[0][0] = 1;
for (int i = 1; i <= m; i++) {
f[i][0] = f[i - 1][0];
//Right
for (int j = 1; j <= i; j++)
f[i][j] = (f[i - 1][j] + (long long) f[i - 1][j - 1] * (R[i] - (j - 1))) % P;
//Left
for (int j = L[i - 1]; j < L[i]; j++)
for (int k = 0; k <= i; k++)
f[i][k] = (long long) f[i][k] * (i - k - j) % P;
}
return !printf("%d\n", f[m][n]);
}
Problem C: big
当时我想不出C在颓emacs,GMK见状怒喷让我打暴力,遂打了5min的暴力。最后我36分他24分。
正解是从来没完全掌握过的Trie树。为什么说他从来没完全掌握过呢?因为我经常口胡却从来没写过。。。就像上次的启发式合并
首先是题目给的那个奇怪操作,等价于\((x >> (n - 1)) + (x << 1)\)我居然没看出来就是把最高位移到最低位。。。。Labelray:cwy你好呆喔
我们就设这个操作为\(\omega(x) = (x >> (n - 1)) + (x << 1)\),把给的数组的前缀异或和pre[]和后缀异或和suf[]记下来。
要求的柿子:\(\omega (x \oplus pre_i) \oplus suf_{i + 1} = \omega (x) \oplus (\omega (pre_i) \oplus suf_{i + 1})\).
最后成了求最大最小值。。。老套路,上trie。
用dfs在trie上跑:
1.下面有0和1 你必被异或成0,直接下一层
2.下面有0或1 贪心一下,这位肯定能搞成1
这题充分暴露出cwy不会Trie的现实。。。。
#include <bits/stdc++.h>
const int N = 100000 + 233;
int n, m, tot, ans, cnt, a[N], pre[N], suf[N], trie[N << 5][2];
void insert(int x) {
for (int i = n - 1, p = 0; i >= 0; i--) {
int t = (x >> i) & 1;
if (!trie[p][t]) trie[p][t] = ++tot;
p = trie[p][t];
}
}
void dfs(int p, int k, int x) {
if (trie[p][0] && trie[p][1]) {
dfs(trie[p][0], k - 1, x);
dfs(trie[p][1], k - 1, x);
} else if (trie[p][0]) {
dfs(trie[p][0], k - 1, x + (1 << k));
} else if (trie[p][1]) {
dfs(trie[p][1], k - 1, x + (1 << k));
} else {
if (x > ans) ans = x, cnt = 1;
else if (x == ans) cnt++;
}
}
signed main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++)
pre[i] = pre[i - 1] ^ ((2 * a[i] / (1 << n) + 2 * a[i]) % (1 << n));
for (int i = m; i >= 1; i--)
suf[i] = suf[i + 1] ^ a[i];
for (int i = 0; i <= m; i++)
insert(pre[i] ^ suf[i + 1]);
dfs(0, n - 1, 0);
return !printf("%d\n%d\n", ans, cnt);
}