Codeforces Round #686 (Div. 3)

A - Special Permutation

int main() {
	IOS;
	for (cin >> _; _; --_) {
		cin >> n;
                rep (i, 2, n) cout << i << ' '; cout << "1
";
	}
	return 0;
}

B - Unique Bid Auction

stl 模拟

int main() {
	IOS;
	for (cin >> _; _; --_) {
		cin >> n;
                map<int, int> a; set<int> b;
                rep (i, 1, n) {
                    cin >> m;
                    if (b.count(m)) continue;
                    else if (a.count(m)) b.insert(m), a.erase(m);
                    else a[m] = i;
                }
                if (!a.empty()) cout << (*a.begin()).se << '
';
                else cout << "-1
";
	}
	return 0;
}

C - Sequence Transformation

模拟

int main() {
	IOS;
	for (cin >> _; _; --_) {
		cin >> n;
                vector<vector<PII>> a(n + 1);
                rep (i, 1, n) {
                    cin >> b[i];
                    if (b[i] == b[i - 1]) ++a[b[i]].back().se;
                    else a[b[i]].pb({ i, i });
                }
                int ans = 2e9;
                for (auto &i : a) if (!i.empty()) umin(ans, i.size() + 1 - (i[0].fi == 1) - (i.back().se == n));
                cout << ans << '
';
	}
	return 0;
}

E - Number of Simple Paths

基环树, 子树节点 互相到达, 不同子树之间有两条路相互到达

int main() {
	IOS;
	for (cin >> _; _; --_) {
		ll n; cin >> n; tot = 0;
                rep (i, 1, n) h[i] = deg[i] = 0, sz[i] = 1;
                rep (i, 1, n) {
                    int u, v; cin >> u >> v;
                    add(u, v); add(v, u); ++deg[u], ++deg[v];
                }
                queue<int> q;
                rep (i, 1, n) if (deg[i] == 1) q.push(i);
                while (!q.empty()) {
                    int x = q.front(); q.pop();
                    for (int i = h[x]; i; i = ne[i]) {
                        int y = to[i];
                        if (deg[y] == 1) continue;
                        if (--deg[y] == 1) q.push(y);
                        sz[y] += sz[x];
                    }
                }
                ll ans = (ll)n * (n - 1);
                rep (i, 1, n) if (deg[i] == 2) ans -= (ll)sz[i] * (sz[i] - 1) / 2;
                cout << ans << "
"; 
	}
	return 0;
}

F

我看榜一是 stl 做的, 大家有兴趣可以看下一

我是线段树 + 倍增

线段树维护的是区间最小值

预处理 mx[i] 表示 (i ~ n) 的最大值

从左往右枚举 x, 再倍增y,

复杂度 (nlog^2n)

struct BIT {
	static const int N = 2e5 + 5;

	struct node {
		int l, r, val;
	} tr[N << 2];

	void build(int rt, int l, int r, int *a) {
		tr[rt].l = l, tr[rt].r = r;
		if (l == r) { tr[rt].val = a[l]; return; }
		int mid = l + r >> 1;
		build(rt << 1, l, mid, a); build(rt << 1 | 1, mid + 1, r, a);
		tr[rt].val = min(tr[rt << 1].val, tr[rt << 1 | 1].val);
	}

	int ask(int rt, int l, int r) {
		if (tr[rt].l >= l && tr[rt].r <= r) return tr[rt].val;
		int ans = 2e9, mid = tr[rt].l + tr[rt].r >> 1;
		if (mid >= l) umin(ans, ask(rt << 1, l, r));
		if (r > mid) umin(ans, ask(rt << 1 | 1, l, r));
		return ans;
	}
} bit;

const int N = 2e5 + 5;

int n, m, _, k;
int a[N], mx[N];

int main() {
	IOS;
	for (cin >> _; _; --_) {
		cin >> n; mx[n + 1] = m = k = 0;
		rep (i, 1, n) cin >> a[i];
		bit.build(1, 1, n, a);
		per (i, n, 1) mx[i] = max(mx[i + 1], a[i]);
		rep (i, 1, n) {
			umax(m, a[i]);
			if (mx[i + 2] < m) break;
			k = i;
			per (j, 17, 0) {
				int c = k + (1 << j);
				if (c < n && mx[c + 1] >= m && bit.ask(1, i + 1, c) >= m) k = c;
			}
			if (k > i && mx[k + 1] == m && bit.ask(1, i + 1, k) == m) { m = i; break; }
			else k = 0;
		}
		if (k) cout << "YES
" << m <<  ' ' << k - m << ' ' << n - k << '
';
		else cout << "NO
";
	}
	return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14035224.html