NOI Online Round 2 improves group online autism

It's hard not having breakfast today.

Before the exam, I was playing with yesterday's Niu ke.com ds question It's time to tune in.

By the end of the exam, I haven't finished writing, and I'm getting grumpy.

\(T_1 : \texttt{color}\)

First, judge the points of \ (k = 1 \) and \ (x = y \).

Then make \ (x < y \), obviously greedy to choose \ (Y \), because there must be a \ (x \) between every two \ (Y \), which must meet the restrictions.

\The function of (y \) can be seen as segmentation \ (x \), and then the question becomes how many \ (x \) a paragraph can have at most.

Obviously, \ (x \) starting position is better than the front position (in a paragraph). According to peishu theorem, we can know that the front position is \ (\ gcd(x,y) \).

The most frequent occurrence of a segment is \ (1 + \lfloor \frac {y - gcd(x,y)} {x} \rfloor \).

Journey:

First I think of greed, then I think of peishu theorem directly.

I finished it in about 10 min utes, and I didn't care much about it.

Expected score: 100 pts

Code

#include <bits/stdc++.h>

using namespace std;

inline int read() {
	int x = 0; char ch = getchar();
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
	return x;
}

inline int gcd(int x, int y) { return y ? gcd(y, x % y) : x; }

int main() {
	freopen("color.in", "r", stdin);
	freopen("color.out", "w", stdout);
	int Case = read(), x, y, g, r, k;
	while(Case--) {
		x = read(), y = read(), k = read();
		if(k == 1) {
			puts("No");
			continue;
		} else if(x == y) {
			puts("Yes");
			continue;
		}
		if(x > y) swap(x, y);
		g = gcd(y, x);
		r = 1 + (y - g - 1) / x;
		puts(r < k ? "Yes" : "No");
	}
	return 0;
}

\(T_2 : \texttt{sequence}\)

Consider what to do without that square.

Scan from left to right, and count the sum of \ (f \) with \ (i \) as the right endpoint.

The record \ (las_x \) indicates where the last \ (x \) occurred.

Then adding a number \ (a \) is equivalent to adding \ (1 \) to all \ (f \) values of \ (idx \ in (Las {a \}, I] \).

It can be maintained by modifying the segment tree of interval query with interval.

Now consider the answer squared.

\((x + d)^2 = x^2 + 2dx + d^2 \), the line tree can maintain the sum of squares, the sum of intervals, and the length of intervals.

Note: do not take module in the line segment tree, just open unsigned long long. Or I can't seem to run

Journey:

At first, I saw this problem, and I felt that if there was no square, I would just scan from left to right and use some simple data structure to do it.

After thinking about it, I found that this problem should also be relatively simple, and I can do it by changing maintenance sum into maintenance sum of squares.

And then I wrote about 40 min utes, and then I wrote about violent pictures.

Expected score: 100 pts

Code

#include <bits/stdc++.h>
#define N 1000005
#define Siz (N << 2)

using namespace std;

typedef unsigned long long ULL;

const int mod = 1e9 + 7;

int n, ll, rr;
int a[N], las[N];
int disc[N];

inline int read() {
	int x = 0; char ch = getchar();
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
	return x;
}

namespace SMT {
#define lch(x) (x << 1)
#define rch(x) (x << 1 | 1)
	ULL s2[Siz], s1[Siz];
	int s0[Siz], tag[Siz];
	inline void update(int u) {
		s2[u] = s2[lch(u)] + s2[rch(u)];
		s1[u] = s1[lch(u)] + s1[rch(u)];
	}
	inline void pushdown(int u) {
		if(tag[u]) {
			int l = lch(u), r = rch(u), d = tag[u];
			s2[l] = s2[l] + 2 * d * s1[l] + 1ULL * s0[l] * d * d;
			s1[l] = s1[l] + 1ULL * s0[l] * d;
			tag[l] = tag[l] + d;
			s2[r] = s2[r] + 2 * d * s1[r] + 1ULL * s0[r] * d * d;
			s1[r] = s1[r] + 1ULL * s0[r] * d;
			tag[r] = tag[r] + d;
			tag[u] = 0;
		}
	}
	void build(int u, int l, int r) {
		s0[u] = r - l + 1;
		if(l == r) return void();
		int mid = l + r >> 1;
		build(lch(u), l, mid);
		build(rch(u), mid + 1, r);
	}
	void modify(int u, int l, int r) {
		if(ll <= l && r <= rr) {
			s2[u] = s2[u] + 2 * s1[u] + s0[u];
			s1[u] = s1[u] + s0[u];
			++tag[u];
			return void();
		} pushdown(u);
		int mid = l + r >> 1;
		if(ll <= mid) modify(lch(u), l, mid);
		if(mid < rr) modify(rch(u), mid + 1, r);
		update(u);
	}
	ULL query(int u, int l, int r) {
		if(ll <= l && r <= rr) return s2[u];
		pushdown(u);
		int mid = l + r >> 1;
		if(rr <= mid) return query(lch(u), l, mid);
		else if(mid < ll) return query(rch(u), mid + 1, r);
		else return query(lch(u), l, mid) + query(rch(u), mid + 1, r);
	}
#undef lch
#undef rch
}

int main() {
	freopen("sequence.in", "r", stdin);
	freopen("sequence.out", "w", stdout);
	n = read();
	for(int i = 1; i <= n; ++i)
		disc[i] = a[i] = read();
	sort(disc + 1, disc + n + 1);
	int tot = unique(disc + 1, disc + n + 1) - disc - 1;
	for(int i = 1; i <= n; ++i)
		a[i] = lower_bound(disc + 1, disc + tot + 1, a[i]) - disc;
	
	int ans = 0;
	SMT::build(1, 1, n);
	for(int i = 1; i <= n; ++i) {
		ll = las[a[i]] + 1, rr = i;
		SMT::modify(1, 1, n);
		las[a[i]] = i;
		ll = 1, rr = i;
		ans = (ans + SMT::query(1, 1, n)) % mod;
	}
	printf("%d\n", ans);
	return 0;
}

I feel stable now. I went to the school canteen to buy food.

Waves, waves, decadent.

\(T_3 : \texttt{match}\)

The writer came out and was beaten!

In this problem, the knapsack on the tree needs to run \ (O(n^2) \) obviously to make use of \(\ color{DeepSkyBlue} {this question} \) 's trick.

The meaning of the first question is very simple. Just go to the backpack.

But when I was almost done... The topic has been updated, which is totally different from the original one. wdnmd

The second time, I feel that it's troublesome. I may have to forgive and scold.

The record \ (f {u, X} \) indicates the number of schemes matching at least \ (x \) pairs in the subtree of \ (U \), which should be multiplied by a factor at last.

Then I was also very difficult to code out, but has not been adjusted correctly, began to close.

Later, I found that the title was wrong, the order of the game was disordered, and there was no need to multiply the sum of groups when transferring.

At last it was about 11:59, but... The spicy chicken page of NOI is not available.

Expected score: none.

Code

#include <bits/stdc++.h>
#define N 5005

using namespace std;

const int mod = 998244353;

int n, m;
int head[N], nex[N << 1], to[N << 1], ecnt;
int fac[N + 5], ifac[N + 5];

inline void addE(int u, int v) {
	to[++ecnt] = v;
	nex[ecnt] = head[u], head[u] = ecnt;
}

int fpm(int x, int y) {
	int r = 1;
	while(y) {
		if(y & 1) r = 1LL * r * x % mod;
		x = 1LL * x * x % mod, y >>= 1;
	}
	return r;
}

inline int perm(int x, int y) { return 1LL * fac[x] * ifac[x - y] % mod; }
inline int comb(int x, int y) { return 1LL * perm(x, y) * ifac[y] % mod; }

int f[N][N], g[N], F[N];
int siz[N], sa[N], sb[N], color[N];

void dfs(int u, int fa) {
	f[u][0] = 1;
	for(int I = head[u], v; I; I = nex[I]) {
		v = to[I]; if(v == fa) continue;
		dfs(v, u);
		for(int i = 0; (i << 1) <= siz[u] + siz[v]; ++i) g[i] = 0;
		for(int i = 0; (i << 1) <= siz[u]; ++i)
			for(int j = 0; (j << 1) <= siz[v]; ++j)
				g[i + j] = (g[i + j] + 1LL * f[u][i] * f[v][j]) % mod;
		siz[u] += siz[v], sa[u] += sa[v], sb[u] += sb[v];
		for(int i = 0; (i << 1) <= siz[u]; ++i) f[u][i] = g[i];
	} ++siz[u];

	if(!color[u]) {
		for(int i = sa[u] - 1; i >= 0; --i)
			f[u][i + 1] = (f[u][i + 1] + 1LL * (sa[u] - i) * f[u][i]) % mod; 
	} else {
		for(int i = sb[u] - 1; i >= 0; --i)
			f[u][i + 1] = (f[u][i + 1] + 1LL * (sb[u] - i) * f[u][i]) % mod;
	}
}

int main() {
	freopen("match.in", "r", stdin);
	freopen("match.out", "w", stdout);
	scanf("%d", &n), m = n >> 1;
	for(int i = 1; i <= n; ++i) {
		char ch = getchar();
		while(!isdigit(ch)) ch = getchar();
		color[i] = ch - '0';
		if(color[i]) ++sa[i];
		else ++sb[i];
	}
	for(int i = 1, u, v; i < n; ++i) {
		scanf("%d %d", &u, &v);
		addE(u, v), addE(v, u);
	}
	
	fac[0] = 1;
	for(int i = 1; i <= N; ++i) fac[i] = 1LL * i * fac[i - 1] % mod;
	ifac[N] = fpm(fac[N], mod - 2);
	for(int i = N; i; --i) ifac[i - 1] = 1LL * i * ifac[i] % mod;
	
	dfs(1, 0);
	
	for(int i = 0; i <= m; ++i)
		F[i] = 1LL * f[1][i] * fac[m - i] % mod;
	for(int i = m; i >= 0; --i)
		for(int j = i - 1; j >= 0; --j)
			F[j] = (F[j] - 1LL * comb(i, j) * F[i] % mod + mod) % mod;
	for(int i = 0; i <= m; ++i)
		printf("%d\n", F[i]);
	return 0;
}

Conclusion:

  1. Write two questions do not feel very stable, to put the mentality.
  2. Be sure to have breakfast in advance.

Posted by sem_db on Sat, 25 Apr 2020 22:08:51 -0700