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);
}
posted @ 2019-08-01 21:11  Gekoo  阅读(179)  评论(6编辑  收藏  举报