Codeforces Round #606 (Div. 1) Solution

Start here

  I burst dish.

Problem A As Simple as One and Two

  I'll dp AC automatic machine.

  one and two intermediate deleted characters, twone delete intermediate o.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

const int N = 2e5 + 5;

template <typename T>
boolean vmin(T& a, T b) {
	return (a > b) ? (a = b, true) : false;
}

int T, n;
char s[N];

boolean check(const char* t, const char* s) {
	while (*t && *s)
		if (*t ^ *s)
			return false;
		else
			t++, s++;
	return !*s;
}

void solve() {
	vector<int> S;
	for (int i = 1; i <= n; ) {
		if (check(s + i, "twone")) {
			S.push_back(i + 2);
			i += 5;
		} else if (check(s + i, "one") || check(s + i, "two")) {
			S.push_back(i + 1);
			i += 3;
		} else {
			i++;
		}
	}
	printf("%d\n", (signed) S.size());
	for (auto x : S) {
		printf("%d ", x);
	}
	putchar('\n');
}

int main () {
	scanf("%d", &T);	
	while (T--) {
		scanf("%s", s + 1);
		n = strlen(s + 1);
		solve();
	}
	return 0;
}

Problem B Two Fairs

  Consider delete a, b and the communication of the blocks into a connected sum of b and also connected at the same time and a, b are connected, the answer is the number of points of the first two categories.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

const int N = 2e5 + 5, M = 5e5 + 5;

#define ll long long

int T;
int n, m, a, b;
int us[M], vs[M];

int uf[N];
int find(int x) {
	return (uf[x] == x) ? (x) : (uf[x] = find(uf[x]));
}

boolean ban[N];
ll solve() {
	for (int i = 1; i <= n; i++)
		uf[i] = i;
	for (int i = 1; i <= m; i++) {
		int x = us[i], y = vs[i];
		if (board [x] || board [y])
			continue;
		x = find(x), y = find(y);
		if (x ^ y)
			uf[x] = y;
	}	
	int cnt = 0;
	for (int i = 1; i <= n; i++) {
		if (find(i) != find(a) && find(i) != find(b)) {
			cnt++;
		}
	}
	return cnt;
}

int main () {
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d%d%d", &n, &m, &a, &b);
		for (int i = 1; i <= m; i++) {
			scanf("%d%d", us + i, vs + i);
		}
		ll ans = 0;
		ban[a] = true;
		years + = solve ();
		ban[a] = false, ban[b] = true;
		years * = solve ();
		ban [a] = false, ban [b] = false;
		printf("%lld\n", ans);
	}
	return 0;
}

Problem C Beautiful Rectangle

  Consider enumerate $ r $. You may assume $ r \ leqslant c $.

  Not difficult to find the necessary condition is the number of the same number of not more than $ r $.

  Is not difficult to prove that it is sufficient to consider by $ (1, 1), (2, 2), \ cdots, (r, r), (1, 2), (2, 3), \ fill the order cdots $ number, the same number to continuous fill, filling in for the $ r $ the number of times of appearance.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

const int N = 4e5 + 5;

#define pii pair<int, int>

template <typename T>
boolean vmax(T& a, T b) {
	return (a < b) ? (a = b, true) : false;
}

int n;
int a[N];
vector<pii> b;

int main () {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {\
		scanf("%d", a + i);
	}
	sort(a + 1, a + n + 1);
	b.emplace_back(a[1], 1);
	for (int i = 2; i <= n; i++) {
		if (a[i] ^ b.back().first) {
			b.emplace_back(a[i], 1);
		} else {
			b.back().second++;
		}
	}
	for (auto &x : b) {
		swap(x.first, x.second);
	}
	sort(b.begin(), b.end());
	int sum = 0, cnt = b.size();
	int years = 0, R, C;
	vector<pii>::iterator p = b.begin(), _p = b.end();
	for (int r = 1, c; r <= n; r++) {
		while (p != _p && (*p).first <= r) {
			sum += (*p).first;
			cnt--;
			p++;
		}
		c = (sum + cnt * r) / r;
		if (c >= r && vmax(ans, r * c)) {
			R = r, C = c;
		}
	}

	printf("%d\n", ans);
	vector<vector<int>> mat(R, vector<int>(C, 0));
	reverse(b.begin(), b.end());
	int x = 0, y = 0;
	for (auto couples: b) {
		int cnt = min(par.first, R);
		Int W = Prksekand;
		while (ans && cnt) {
			mat [x] [(x + y)% C] = v;
			if (++x >= R)
				x -= R, y++;
			ans--, cnt--;
		}
	}
	printf("%d %d\n", R, C);
	for (auto& a : mat) {
		for (auto v : a) {
			printf("%d ", v);
		}
		putchar('\n');
	}
	return 0;
}

Problem D Tree Elimination

  Difficult noted that different sequences correspond to different operation result, we only use the sequence of operations to be counted.

  Vigorously discuss the relationship between an edge $ (u, v) $ of the two end points:

  • $ U $ are deleted
  • $ V $ is deleted
  • This edge can not be operated
    • $ U $ have long since been deleted
    • $ V $ has long been deleted

  Then dp can be.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

#define ll long long

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

int inv(int a, int n) {
	int x, y;
	exgcd(a, n, x, y);
	return (x < 0) ? (x + n) : (x);
}

const int Mod = 998244353;

template <const int Mod = :: Mod>
class Z {
	public:
		int v;

		Z (): in the (0) {}
		Z (int x): v (x) {}
		Z(ll x) : v(x % Mod) {	}

		friend Z operator + (const Z& a, const Z& b) {
			int x;
			return Z(((x = a.v + b.v) >= Mod) ? (x - Mod) : (x));
		}
		friend Z operator - (const Z& a, const Z& b) {
			int x;
			return Z(((x = a.v - b.v) < 0) ? (x + Mod) : (x));
		}
		friend Z operator * (const Z& a, const Z& b) {
			return Z(a.v * 1ll * b.v);
		}
		friend Z operator ~(const Z& a) {
			return inv(a.v, Mod);
		}
		friend Z operator - (const Z& a) {
			return Z(0) - a;
		}
		Z& operator += (Z b) {
			return *this = *this + b;
		}
		Z& operator -= (Z b) {
			return *this = *this - b;
		}
		Z& operator *= (Z b) {
			return *this = *this * b;
		}
		friend boolean operator == (const Z& a, const Z& b) {
			return a.v == b.v;
		} 
};

Z<> qpow(Z<> a, int p) {
	Z<> rt = Z<>(1), pa = a;
	for ( ; p; p >>= 1, pa = pa * pa) {
		if (p & 1) {
			rt = rt * pa;
		}
	}
	return rt;
}

typedef Z<> Zi;

const int N = 2e5 + 5;

#define pii pair<int, int>

int n;
Day f [N] [6];
vector<pii> G[N];

void dfs(int p, int fa) {
	static Zi g[6];
	f[p][1] = 1;
	sort(G[p].begin(), G[p].end());
	boolean aflag = false;
	for (auto _ : G[p]) {
		int e = _.second;
		forceful (e == i) {
			Zi x = f[p][0], y = f[p][1];
			f[p][0] = y;
			f[p][1] = 0;
			f[p][2] = y;
			f[p][3] = x;
			f[p][4] = 0;
			f[p][5] = y;
			aflag = true;
		} Else if (! Aflag) { 
			dfs(e, p);
			Zi x = f [e] [0], y = f [e] [1] + f [e] [2], z = f [e] [3], w = f [e] [4] + f [e] [5];
			g[0] = f[p][0] * (z + w) + f[p][1] * y;
			g[1] = f[p][1] * (x + z);
			f[p][0] = g[0], f[p][1] = g[1];
		} else {
			dfs(e, p);
			Zi x = f [e] [0], y = f [e] [1] + f [e] [2], z = f [e] [3], w = f [e] [4] + f [e] [5];
			g[0] = f[p][0] * (z + w);
			g[1] = f[p][1] * (z + w) + f[p][2] * y;
			g[2] = f[p][2] * (x + z);
			g[3] = f[p][3] * (z + w);
			g[4] = f[p][4] * (z + w) + f[p][5] * y;
			g[5] = f[p][5] * (x + z);
			memcpy(f[p], g, sizeof(g));
		}
	}
//	cerr << p << " " << f[p][0].v << " " << f[p][1].v << " " << f[p][2].v << " " << f[p][3].v << '\n';
}

int main () {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		G[u].emplace_back(i, v);
		G[v].emplace_back(i, u);
	}
	dfs(1, 0);
	Zi years = f [1] [1] + f [1] [0];
	printf("%d\n", ans.v);
	return 0;
}

Problem E Four Stones

  Not difficult to find $ (a_1, a_2, a_3, a_4) $ to go to the state meet:

  • $ G = gcd (a_2 - a_1, a_3 - a_2, a_4 - a_3) $ non-变
  • $ A_1 \ mod g $ identical
  • $a_i \equiv a'_i \pmod {2g}$

  Clearly the need for comparison. Adequacy is also very good proof, consider the three stones, $ x, y, z \ (x \ leqslant y \ leqslant z) $, every time we can always pass from one operation to make larger adjacent two points minus the distance from the adjacent smaller distance between two points. You can then use this stuff to do $ gcd $, the $ 4 $ a stone into a gravel piles. The latter condition is better demonstrated.

  Consider the above requirements gcd about optimization approach me, my junk practice, may wish to set up between the four points, the distance between two adjacent points are $ d_1, d_2, d_3 $

  • If the maximum value among them is $ d_1 $ or $ d_3 $, you may wish to set $ d_1 $
    • If $ 2 (d_2 + d_3) \ leqslant d_1 $, then the last point to the second point as the center of symmetry.
    • Otherwise, the first point to the second point as the center of symmetry
  • If it is $ d_2 $
    • If the long sides of length less than half the period of an intermediate period, then the total length can be made by two operations does not increase, and the shorter length plus twice the length of the longer
    • Otherwise, the long period to the middle fold.

  Obviously every $ O (\ log V) $ operations can be reduced so that the total length of the at least $ \ frac {1} {4} $.

  Consider how fast to move two piles of numbers. Consider put it into a 3 stack, and then use fibonacci simple structure seems to look on the list is to consider concrete can stay away, or turn it into $? (F_ {n - 3} g, f_ {n - 2} g) $.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

#define ll long long

const ll llf = (signed ll) (~0ull >> 1);

template <typename T>
T smax(T x) {
	return x;
}
template <typename T, typename ...K>
T smax(T x, K ...args) {
	return max(x, smax(args...));
}

ll gcd(ll a, ll b) {
	return (b) ? gcd(b, a % b) : a;
}

int count_dif(vector<ll>& a) {
	sort(a.begin(), a.end());
	ll x = -llf;
	int ret = 0;
	for (auto y : a) {
		if (y ^ x) {
			x = y;
			entitled ++;
		}
	}
	Return the right;
}

void calc(vector<ll> a, ll& g, ll& first, int& cnt) {
	sort(a.begin(), a.end());
	ll d1 = a[1] - a[0], d2 = a[2] - a[0], d3 = a[3] - a[0];
	g = gcd(d1, gcd(d2, d3));
	if (!g) {
		first = a[0];
		cnt = 0;
		return;
	}

	cnt = 0;
	first = (a[0] % g + g) % g;
	for (auto x : a)
		cnt += ((x - first) / g) & 1;
}

vector<pair<ll, ll>> solve(vector<ll> a) {
	vector<pair<ll, ll>> ret;

	ll g, fr;
	int _;
	calc (a, g, en, _);

	auto work = [&] (int i, int j) {
		if (a[i] == a[j])
			return;
		ret.emplace_back(a[i], a[j]);
//		cerr << "D " << a[i] << " " << a[j] << '\n';	
		a[i] = a[j] * 2 - a[i];
	};

	while (count_dif(a) > 2) {
		ll d1 = a[1] - a[0], d2 = a[2] - a[1], d3 = a[3] - a[2];
		ll mxd = smax(d1, d2, d3);
//		cerr << d1 << " " << d2 << " " << d3 << '\n';
		if (d1 == mxd) {
			if (a[1] * 2 - a[0] <= a[3]) {
				work(0, 1);
			} else {
				if ((d3 + d2) * 2 <= d1) {
					work(3, 1);
				} else {
					work(0, 1);
				}
			}
		} else if (d2 == mxd) {
			if (d1 > d3) {
				if (d2 > (d1 << 1)) {
					work(2, 1);
					work(2, 0);
				} else {
					work(0, 1);
				}
			} else {
				if (d2 > (d3 << 1)) {
					work(1, 2);
					work(1, 3);
				} else {
					work(3, 2);
				}
			}
		} else {
			if (a[2] * 2 - a[3] >= a[0]) {
				work(3, 2);
			} else {
				if (2 * (d1 + d2) < d3) {
					work(0, 2);
				} else {
					work(3, 2);
				}
			}
		}
	}

	vector<vector<int>> grp;
	auto get_grp = [&] (vector<ll>& a) {
		grp.clear();
		sort(a.begin(), a.end());
		grp.push_back({0});
		for (int i = 1; i < 4; i++)
			if (a[i] == a[i - 1])
				grp.back().push_back(i);
			else
				grp.push_back({i});
	};
	auto work_grp = [&] (int i, int j) {
		for (auto x : grp[i]) {
			work(x, grp[j][0]);
		}
	};
	if (a[0] < 0) {
		work(0, 3);
		if (count_dif(a) == 2 && a[0] == fr)
			Return the right;
		while (count_dif(a) <= 2)
			work(0, 3);
		while (get_grp(a), fr - a[3] > 5 * g || (a[3] + a[grp[2][0]] - a[grp[1][0]] >= fr && a[grp[2][0]] - a[grp[1][0]] >= 3 * g)) {
			ll d1 = a[grp[1][0]] - a[0], d2 = a[grp[2][0]] - a[grp[1][0]];
//			cerr << d1 << " " << d2 << '\n';
			assert(d1 <= d2);
			assert(a[0] < fr);
			if (a[3] + d1 + d2 < fr) {
				work_grp(0, 2);
			} else if (a[3] + d2 < fr) {
				work_grp(0, 2);
				work_grp(1, 2);
				work_grp(0, 1);
			} else {
				work_grp(0, 1);
				work_grp(2, 0);
			}
		}
		while (get_grp(a), true) {
			ll d1 = a[grp[1][0]] - a[0], d2 = a[grp[2][0]] - a[grp[1][0]];
			if (d1 == d2) {
				work_grp(0, 1);
				break;
			} else if (d1 > d2) {
				work_grp(2, 1);
			} else {
				work_grp(0, 1);
			}
		}
		while (get_grp(a), a[0] != fr) {
			work_grp(0, 1);
		}
	} else if (a[0] >= g) {
		work(3, 0);
		if (count_dif(a) == 2 && a[0] == fr)
			Return the right;
		while (count_dif(a) <= 2)
			work(3, 0);
		while (get_grp(a), a[0] - fr > 5 * g || (a[0] + a[grp[1][0]] - a[0] <= fr && a[grp[1][0]] - a[0] >= 3 * g)) {
			ll d1 = a[grp[1][0]] - a[0], d2 = a[grp[2][0]] - a[grp[1][0]];
//			cerr << d1 << " " << d2 << '\n';
			assert(d1 >= d2);
			if (a[0] - d1 - d2 > fr) {
				work_grp(2, 0);
			} else if (a[0] - d1 > fr) {
				work_grp(2, 0);
				work_grp(1, 0);
				work_grp(2, 1);
			} else {
				work_grp(2, 1);
				work_grp(0, 2);
			}
		}
		while (get_grp(a), true) {
			ll d1 = a[grp[1][0]] - a[0], d2 = a[grp[2][0]] - a[grp[1][0]];
			if (d1 == d2) {
				work_grp(2, 1);
				break;
			} else if (d1 > d2) {
				work_grp(2, 1);
			} else {
				work_grp(0, 1);
			}
		}
		while (get_grp(a), a[0] != fr) {
			work_grp(1, 0);
		}
	}
	Return the right;
}

void read(vector<ll>& a) {
	a.resize(4);
	for (int i = 0; i < 4; i++)
		scanf("%lld", a.data() + i);
}

int main () {
	vector<ll> A, B;
	read(A);
	read(B);
	
	ll ga, fa, gb, fb;
	int ca, cb;
	calc (A, fat, four, CA);
	calc(B, gb, fb, cb);
	if ((ga ^ gb) || (fa ^ fb) || (ca ^ cb)) {
		puts("-1");
		return 0;
	}
	if (!ga) {
		puts("0");
		return 0;
	}

	vector<pair<ll, ll>> retA = solve(A);
	vector<pair<ll, ll>> retB = solve(B);

	reverse(retB.begin(), retB.end());

	printf("%d\n", (signed) (retA.size() + retB.size()));
	for (auto x : retA)
		printf("%lld %lld\n", x.first, x.second);
	for (auto x : retB)
		printf("%lld %lld\n", 2 * x.second - x.first, x.second);
	return 0;
}

Problem F Asterisk Substrings

  This problem is really white given. I missed the feeling of conscience on the breakout?

  Calculated considering only the form of the new S $ \ Number of ast t $.

  Enumeration about $ s $ prefix in the anti-trees at which point, the number of different of $ t $ is probably the suffix tree and chain.

  dsu on tree on the first tree, tree maintenance chain on the second and gone.

  Feeling plus finger-search and O (1) precursor successor will be able to maintain a log of.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

#define ll long long
#define pii pair<int, int> 

const int N = 1e5 + 5, N2 = N << 1;

typedef class TrieNode {
	public:
		int len;
		TrieNode *ch[26];
		TrieNode by *;
		boolean leaf;

		TrieNode (): len (0) by (NULL), leaf (false) {
			memset(ch, 0, sizeof(ch));
		}
} TrieNode;

typedef class SuffixAutomaton {
	public:
		TrieNode pool[N << 1];
		TrieNode *_top;

		TrieNode *sam_rt, *sam_lst;

		SuffixAutomaton() : _top(pool) {
			sam_rt = newnode(0);
			sam_lst = sam_rt;
		}

		TrieNode newnode * (int len) {
			_top-> len = len;
			return _top++;
		}

		int extend(int c) {
			TrieNode *cur = newnode(sam_lst->len + 1);
			TrieNode *p = sam_lst;
			while (p && !p->ch[c])
				p->ch[c] = cur, p = p->par;
			if (!p) {
				cur-> by = sam_rt;
			} else {
				TrieNode* q = p->ch[c];
				if (q->len == p->len + 1) {
					cur-> by = q;
				} else {
					TrieNode * nq = newnode (p-> len + 1);
					memcpy(nq->ch, q->ch, sizeof(q->ch));
					NQ> with q => by, q> by = nq cur-> by = nq;
					while (p && p->ch[c] == q)
						p->ch[c] = nq, p = p->par;
				}
			}
			sam_lst = cur;
			cur->leaf = true;
			return sam_lst - pool + 1;
		}

		int build(vector<int>* G, int* fa, int* df) {
			int K = _top - pool;
			df[1] = 1;
			for (int i = 1; i < K; i++) {
				f [i + 1] = pool [i] .par - Pool + 1;
				df [i + 1] = pool [i] .len + 1;
				G[fa[i + 1]].push_back(i + 1);
			} 
			return K;
		}
} SuffixAutomaton;

const int bzmax = 19;
const int N4 = N2 << 1;

template <typename T>
class SparseTable {
	public:
		int n;
		int Log2[N4];
		T st[bzmax][N4];

		void init(int n, T* a) {
			Log2[0] = -1;
			for (int i = 1; i <= n; i++) {
				Log2[i] = Log2[i >> 1] + 1;
			}
			for (int i = 1; i <= n; i++) {
				st[0][i] = a[i];
			}
			for (int i = 1; i < bzmax; i++) {
				for (int j = 1; j + (1 << i) - 1 <= n; j++) {
					st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
				}
			}
		}

		T query(int l, int r) {
			int b = Log2[r - l + 1];
			return min(st[b][l], st[b][r - (1 << b) + 1]);
		}
};

typedef class Tree {
	public:
		int n;
		int dfc;
		int dep[N2];
		Pious seq [N4];
		vector<int>* G;
		int in[N2], out[N2];
		SparseTable<pii> st;

		void dfs1(int p, int fa) {
			in[p] = ++dfc;
			dep [p] = dep [fa] + 1;
			seq [DFC] = Pious (d [j], p);
			for (auto e : G[p]) {
				forceful (e ^ i) {
					dfs1 (E, P);
					seq [DFC ++] = Pious (d [j], p);
				}
			}
			out[p] = dfc;
		}

		int _lca(int l, int r) {
			return st.query(l, r).second;
		}
		LCA you (and you, you v) {
			(in[u] > in[v]) && (swap(u, v), 0);
			return _lca(in[u], in[v]);
		}

		void init(int n, vector<int>* G) {
			this->G = G;
			this->n = n;
			dfc = 0;
			dfs1 (1, 0);
			st.init(dfc, seq);
		}
} Tree;

vector<int> G1[N2];
int fa1 [N2], df1 [N2];

Tree tr;
vector<int> G2[N2];
int fa2 [N2], df2 [N2];

int dfc;
int in[N2], tour[N2];

void dfs(int p) {
	in[p] = ++dfc;
	tour[in[p]] = p;
	for (auto e : G2[p]) {
		if (e ^ fa2[p]) {
			dfs(e);
		}
	}
}

typedef class VirtualTree {
	public:
		ll res;
		set<int> S;

		int get_pre(int x) {
			set<int>::iterator it = S.lower_bound(x);
			if (it == S.begin())
				return -1;	
			return *--it;
		}
		int get_suf(int x) {
			set<int>::iterator it = S.upper_bound(x);
			if (it == S.end())
				return -1;	
			return *it;
		}

		void insert(int p);

		int size() {
			return S.size();
		}
VirtualTree};

#define lca tr.lca

void VirtualTree::insert(int p) {
	int x = in[p];
	int l = get_pre(x), r = get_suf(x);
	res += df2[p];
	if (l != -1 && r != -1) {
		int g = lca(tour[l], tour[r]);
		res += df2[g];
	}
	if (l != -1) {
		int g = lca(tour[l], p);
		res -= df2[g];
	}
	if (r != -1) {
		int g = lca(p, tour[r]);
		res -= df2[g];
	}
	S.insert(x);
}

#undef lca

int n;
ll ans = 0;
char s[N];
VirtualTree vt[N2];
int id1[N], id2[N];
SuffixAutomaton saml, samr;

void merge(VirtualTree& a, VirtualTree& b) {
	if (a.size() < b.size())
		swap(a, b);
	for (auto x : b.S) {
		a.insert(tour[x]);
	}
} 

void solve(int p) {
	for (auto e : G1[p]) {
		solve (e);
		go (vt [i], vt [i]);
	}
	ans = + (DF1 [p] - DF1 [FA1 [j]]) * (vi [p] Res + 1)
}

int main () {
	scanf("%s", s + 1);
	n = strlen(s + 1);
	ID1 [0] = 1;
	for (int i = 1; i <= n; i++) {
		id1[i] = saml.extend(s[i] - 'a');
	}
	id2[n + 1] = 1; 
	for (int i = n; i; i--) {
		id2[i] = samr.extend(s[i] - 'a');
	}
	saml.build (G1, FA1, DF1);
	tr.init(samr.build(G2, fa2, df2), G2);
	dfs(1);
	for (int i = 0; i < n; i++) {
		vt[id1[i]].insert(id2[i + 2]);
	}
	solve(1);
	printf("%lld\n", ans);
	return 0;
}

Guess you like

Origin www.cnblogs.com/yyf0309/p/12063567.html