• 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
    ", 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
    %d
    ", ans, cnt);
    }
    
  • 相关阅读:
    aspnet_regiis.exe -i 报 “此操作系统版本不支持此选项”
    c# winform如何屏蔽键盘上下左右键
    六大设计原则
    hexo发布失败
    springboot静态资源添加版本号控制版本更新
    parallels desktop无法连接网络无法连接usb解决方法
    @RequestParam使用defaultValue属性设置默认值
    soar以及web页面安装使用
    windows平台下安装nodejs出错2503 2502
    iconfont图标使用
  • 原文地址:https://www.cnblogs.com/gekoo/p/11285382.html
Copyright © 2020-2023  润新知