BJOI2019 Day2 简要题解

T1 arrange

暴力。 Θ ( n m s ) \Theta(nms)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>

#include <numeric>
#include <functional>
#include <algorithm>
#include <limits>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

const int N = 110, S = 110, M = 20010;

int n, m, s;
int a[S][N];
int cur[S];
int dp[M];

int main() {
	scanf("%d%d%d", &s, &n, &m);
	for (int i = 1; i <= s; ++i)
		for (int j = 1; j <= n; ++j)
			scanf("%d", &a[i][j]);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= s; ++j)
			cur[j] = a[j][i] * 2 + 1;
		sort(cur + 1, cur + s + 1);
		for (int j = m; j; --j)
			for (int k = 1; cur[k] <= j && k <= s; ++k)
				dp[j] = max(dp[j], dp[j - cur[k]] + k * i);
	}
	printf("%d\n", dp[m]);
	
	return 0;
}

T2 ray

消元。 Θ ( n ) \Theta(n)

#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <ctime>

#include <numeric>
#include <functional>
#include <algorithm>
#include <limits>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

const int N = 500010, P = 1000000007;

int n;
int mat[N * 2][5], v[N * 2];

int norm(int x) { return x >= P ? x - P : x; }

void exGcd(int a, int b, int& x, int& y) {
	if (!b) {
		x = 1;
		y = 0;
		return;
	}
	exGcd(b, a % b, y, x);
	y -= a / b * x;
}

int inv(int a) {
	int x, y;
	exGcd(a, P, x, y);
	return norm(x + P);
}

void elim(int n) {
	for (int i = 0; i < n; ++i) {
		int in = inv(mat[i][2]);
		for (int j = 2; j < 5; ++j)
			mat[i][j] = mat[i][j] * (ll)in % P;
		v[i] = v[i] * (ll)in % P;
		for (int j = i + 1; j < n && j <= i + 2; ++j) {
			v[j] = (v[j] + (P - mat[j][2 - (j - i)]) * (ll)v[i]) % P;
			for (int k = 3; k < 5; ++k)
				mat[j][k - (j - i)] = (mat[j][k - (j - i)] + (P - mat[j][2 - (j - i)]) * (ll)mat[i][k]) % P;
			mat[j][2 - (j - i)] = 0;
		}
	}
}

int main() {
	scanf("%d", &n);
	int I100 = inv(100);
	for (int i = 0; i <= n * 2; ++i)
		mat[i][2] = 1;
	for (int i = 0; i < n; ++i) {
		int a, b;
		scanf("%d%d", &a, &b);
		mat[(i + 1) << 1][0] = mat[i << 1 | 1][4] = (P - a) * (ll)I100 % P;
		mat[i << 1 | 1][1] = mat[(i + 1) << 1][3] = (P - b) * (ll)I100 % P;
	}
	v[0] = 1;
	elim(n * 2 + 1);
	printf("%d\n", v[n * 2]);
	
	return 0;
}

T3 number

注意到把 i i 在数轴上的 [ i c n t ( i ) , i ] [i-cnt(i), i] 线段涂色,在 [ 0 , n ] [0, n] 上没被染色的部分就是答案,用线段树打 Tag 维护即可。 Θ ( n log n ) \Theta(n \log n)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>

#include <numeric>
#include <set>
#include <functional>
#include <algorithm>
#include <limits>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

struct Node {
	int l, r;
	Node *ls, *rs;
	int tag, s;
	
	void upd() {
		if (tag)
			s = 0;
		else if (l == r)
			s = 1;
		else
			s = ls->s + rs->s;
	}
	
	void ch(int l, int r, int x) {
		if (this->l == l && this->r == r) {
			tag += x;
			upd();
			return;
		}
		if (r <= ls->r)
			ls->ch(l, r, x);
		else if (l >= rs->l)
			rs->ch(l, r, x);
		else {
			ls->ch(l, ls->r, x);
			rs->ch(rs->l, r, x);
		}
		upd();
	}
	
	int qry(int l, int r) {
		if (tag)
			return 0;
		if (this->l == l && this->r == r)
			return s;
		if (r <= ls->r)
			return ls->qry(l, r);
		if (l >= rs->l)
			return rs->qry(l, r);
		return ls->qry(l, ls->r) + rs->qry(rs->l, r);
	}
};

const int N = 150010;

int n, lazy;
int a[N], cnt[N * 4];
Node* seg;

Node* build(int l, int r) {
	static Node pool[N * 8], *ptop = pool;
	Node* p = ptop++;
	p->l = l;
	p->r = r;
	p->s = r - l + 1;
	if (l == r)
		return p;
	int mid = (l + r) >> 1;
	p->ls = build(l, mid);
	p->rs = build(mid + 1, r);
	return p;
}

void inc(int k) {
	if (k > lazy + n) {
		++cnt[k];
	} else {
		if (cnt[k])
			seg->ch(k - cnt[k] + 1, k, -1);
		++cnt[k];
		seg->ch(k - cnt[k] + 1, k, 1);
	}
}

void dec(int k) {
	if (k > lazy + n) {
		--cnt[k];
	} else {
		seg->ch(k - cnt[k] + 1, k, -1);
		if (--cnt[k])
			seg->ch(k - cnt[k] + 1, k, 1);
	}
}

void modify(int k, int x) {
	if (a[k] == x + lazy)
		return;
	if (a[k])
		dec(a[k]);
	a[k] = x + lazy;
	inc(x + lazy);
}

int main() {
	int m;
	scanf("%d%d", &n, &m);
	seg = build(1, (n + m) * 2);
	lazy = m + n;
	for (int i = 1; i <= n; ++i) {
		int x;
		scanf("%d", &x);
		modify(i, x);
	}
	while (m--) {
		int p, x;
		scanf("%d%d", &p, &x);
		if (p == 0) {
			if (x == 1) {
				--lazy;
				if (cnt[lazy + n + 1])
					seg->ch(lazy + n + 1 - cnt[lazy + n + 1] + 1, lazy + n + 1, -1);
			} else {
				++lazy;
				if (cnt[lazy + n])
					seg->ch(lazy + n - cnt[lazy + n] + 1, lazy + n, 1);
			}
		} else
			modify(p, x);
		printf("%d\n", seg->qry(lazy + 1, lazy + n));
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/EI_Captain/article/details/89435513