2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest 11/14

A

#include <iostream>
#include <cstdio>
 
using namespace std;
 
int const N = 100005;
 
int a[N], dfn[N];
int mx[N], mi[N];
 
void update(int x) {
	mx[x] = max(mx[x], dfn[x]);
	mi[x] = min(mi[x], dfn[x]);
}
 
int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		a[i] = i;
		dfn[i] = i;
		mx[i] = mi[i] = i;
	}
	for (int i = 1; i <= m; ++i) {
		int x;
		scanf("%d", &x);
		if (dfn[x] != 1) {
			int pre = a[dfn[x] - 1];
			dfn[x] = dfn[x] - 1;
			dfn[pre] = dfn[pre] + 1;
			swap(a[dfn[x]], a[dfn[pre]]);
			update(x);
			update(pre);
		}
	}
	for (int i = 1; i <= n; ++i)
		printf("%d %d\n", mi[i], mx[i]);
}

B

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=500005,maxm=8005;
int n,m,val[maxm];
bool boo[maxn];
LL ans;
int work(int key)
{
	int res=0,cnt=0;
	for (int L=1,R=m;L<=R;L++)
	{
		while (L<R && val[L]+val[R]<=key) R--,cnt++;
		if (cnt) cnt--;
		res++;
	}
	return res+(cnt+1)/2;
}
bool cmp(int A,int B) { return A>B; }
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1,x;i<=n;i++)
	{
		scanf("%d",&x);
		val[x]++;
	}
	sort(val+1,val+1+m,cmp);
	for (int i=1;i<m;i++)
		for (int j=i+1;j<=m;j++)
			boo[val[i]+val[j]]=true;
	ans=(LL)val[1]*work(val[1]);
	for (int i=val[1]+1;i<=val[1]+val[2];i++)
		if (boo[i]) ans=min(ans,(LL)i*work(i));
	printf("%lld",ans);
	return 0;
}

C

线段树维护左端点的答案就行。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <utility>
 
using namespace std;
 
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
 
int const N = 200005;
int const M = 200000;
 
ll mx[N << 2], lz[N << 2];
struct node {
	ll l, r, p;
} a[N];
int n;
ll m;
vector<node> vec[N];
 
void pushdown(int k) {
	mx[k << 1] += lz[k];
	mx[k << 1 | 1] += lz[k];
	lz[k << 1] += lz[k];
	lz[k << 1 | 1] += lz[k];
	lz[k] = 0;
}
 
void pushup(int k) {
	mx[k] = max(mx[k << 1], mx[k << 1 | 1]);
}
 
void modify(int k, int l, int r, int ql, int qr, ll v) {
	if (ql <= l && r <= qr) {
		mx[k] += v;
		lz[k] += v;
		return;
	}
	int mid = (l + r) >> 1;
	if (lz[k] != 0)
		pushdown(k);
	if (ql <= mid)
		modify(k << 1, l, mid, ql, qr, v);
	if (qr > mid)
		modify(k << 1 | 1, mid + 1, r, ql, qr, v);
	pushup(k);
}
 
ll query_ans(int k, int l, int r, int ql, int qr) {
	if (ql <= l && r <= qr) 
		return mx[k];
	int mid = (l + r) >> 1;
	ll ret = 0;
	if (lz[k] != 0)
		pushdown(k);
	if (ql <= mid)
		ret = query_ans(k << 1, l, mid, ql, qr);
	if (qr > mid)
		ret = max(query_ans(k << 1 | 1, mid + 1, r, ql, qr), ret);
	pushup(k);
	return ret;
}
 
int query(int k, int l, int r, ll v) {
	if (l == r)
		return l;
	int mid = (l + r) >> 1, ret = 0;
	if (lz[k] != 0)
		pushdown(k);
	if (mx[k << 1] == v)
		ret = query(k << 1, l, mid, v);
	else
		ret = query(k << 1 | 1, mid + 1, r, v);
	pushup(k);
	return ret;
}
 
int main() {
	ios::sync_with_stdio(0);
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i].l >> a[i].r >> a[i].p;
		vec[a[i].r].push_back(a[i]);
	}
	int ansl = -1, ansr = -1;
	ll ans = 0;
	for (int i = 1; i <= M; ++i) {
		modify(1, 1, M, 1, i, -m);
		for (auto p : vec[i]) 
			modify(1, 1, M, 1, p.l, p.p);
		ll anss = query_ans(1, 1, M, 1, i);
		if (anss > ans) {
			//fprintf(stderr, ">> %d %d\n", i, anss);
			ans = anss;
			ansr = i;
			ansl = query(1, 1, M, ans);
		}
	}
	if (ans == 0)
		puts("0");
	else {
		auto sub = vector<int>();
		for (int i = 1; i <= n; ++i)
			if (ansl <= a[i].l && a[i].r <= ansr)
				sub.push_back(i);
		cout << ans << ' ' << ansl << ' ' << ansr << ' ' << sub.size() << '\n';
		for (int i = 0; i < (int)sub.size(); ++i) {
			cout << sub[i];
			if (i + 1 == (int)sub.size())
				cout << '\n';
			else
				cout << ' ';
		}
	}
}

D

E

来自coming的补题,2-sat一下

F

#include <iostream>
#include <cstdio>
 
using namespace std;
 
int main() {
	int s;
	cin >> s;
	int ans = s * 10;
	for (int i = 1; i <= s; ++i)
		if (s % i == 0) {
			int oth = s / i;
			int tmp = (i + oth) * 2;
			ans = min(ans, tmp);
		}
	cout << ans << '\n';
}

G

无脑DP,注意边界x

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cassert>
 
using namespace std;
 
using ll = long long;
 
int const N = 200005;
 
int a[N], b[N];
int n, m;
ll s1[N], s2[N];
int f[N], pre[N];
 
void dfs(int x) {
	if (x == 0)
		return;
	dfs(pre[x]);
	printf("%d ", x);
}
 
bool chk(int l, int r) {
	return max(s1[r], s2[r]) - min(s1[l], s2[l]) < m;
}
 
int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &a[i]);
			s1[i] = s1[i - 1] + a[i];
		}
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &b[i]);
			s2[i] = s2[i - 1] + b[i];
		}
		f[0] = 0;
		int lim = n;
		for (int i = 1, p = 0; i <= n; ++i) {
			while (p < i && chk(p, i) == 0)
				++p;
			//assert(p < i);
			if (p == i) {
				lim = i;
				break;
			}
			f[i] = f[p] + 1;
			pre[i] = p;
			//cerr << i << ' ' << f[i] << ' ' << pre[i] << '\n';
		}
		s1[n + 1] = s1[n];
		s2[n + 1] = s2[n];
		int ans = -1, pos = -1;
		for (int i = 0, p = 1; i < lim; ++i) {
			p = max(p, i);
			while (p < lim && chk(i, p + 1))
				++p;
			ll t1 = s1[i], t2 = s2[i];
			ll mi = min(t1, t2);
			t1 -= mi;
			t2 -= mi;
			t1 += s1[p + 1] - s1[i];
			t2 += s2[p + 1] - s2[i];
			if (t1 < m && t2 >= m) {
				ans = f[i];
				pos = i;
				break;
			}
		}
		printf("%d\n", ans);
		if (ans != -1) {
			dfs(pos);
			printf("\n");
		}
	}
}

H

#include <bits/stdc++.h>
using namespace std;
int G,cho,a[12];
int main()
{
	scanf("%d",&G);
	while (G--)
	{
		scanf("%d",&a[0]);
		a[0]++;
		cho=0;
		for (int i=1;i<=9;i++)
		{
			scanf("%d",&a[i]);
			if (a[i]<a[cho]) cho=i;
		}
		if (cho) for (int i=0;i<=a[cho];i++) printf("%d",cho); else
		{
			printf("1");
			for (int i=1;i<=a[0];i++) printf("0");
		}
		printf("\n");
	}
	return 0;
}

I

J

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
 
using namespace std;
 
using ll = long long;
 
int const N = 30005;
 
ll a[N], b[N];
int n;
ll m;
 
bool chk(ll lim) {
	ll ret = 0;
	for (int i = 0; i <= n; ++i)
		b[i] = a[i];
	for (int i = 1; i <= n; ++i) {
		ll can = (b[i] + b[i - 1]) / lim;
		ret += can;
		ll del = can * lim;
		del -= b[i - 1];
		if (del <= 0)
			continue;
		b[i] -= del;
	}
	return ret >= m;
}
 
int main() {
	ios::sync_with_stdio(0);
	int T;
	cin >> T;
	while (T--) {
		cin >> n >> m;
		for (int i = 1; i <= n; ++i)
			cin >> a[i];
		ll l = 1, r = 5e16, ans = 0;
		while (l <= r) {
			ll mid = (l + r) >> 1;
			if (chk(mid)) {
				ans = mid;
				l = mid + 1;
			} else
				r = mid - 1;
		}
		cout << ans * m << '\n';
	}
}

K

L

#include <bits/stdc++.h>
using namespace std;
int G,A,B,C,ans;
int work(int A,int B,int C,int can)
{
	if (A<B) swap(A,B);
	if (A<C) swap(A,C);
	can-=A-B;
	can-=A-C;
	if (can<=0)
		return A; else
		return A+(can+2)/3;
}
int main()
{
	scanf("%d",&G);
	while (G--)
	{
		scanf("%d%d%d",&A,&B,&C);
		ans=work(A/2,A-A/2,C,B);
		ans=min(ans,work(A,C/2,C-C/2,B));
		printf("%d\n",ans);
	}
	return 0;
}

M

倍增一下,每次搞方案就行

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
 
struct Ans {
	std::vector<int> xs, ys;
 
	bool empty() const {
		return xs.empty() || ys.empty();
	}
};
 
void dup (std::vector<Ans> &ans, int n, int mx) {
	int tgt = std::min(n * 2 + 1, mx);
 
	for (auto &c: ans) {
		int n1 = c.xs.size();
		for (int i = 0; i < n1; ++i)
			if (c.xs[i] + n + 1 <= tgt)
				c.xs.push_back(c.xs[i] + n + 1);
 
		int n2 = c.ys.size();
		for (int i = 0; i < n2; ++i)
			if (c.ys[i] + n + 1 <= tgt)
				c.ys.push_back(c.ys[i] + n + 1);
	}
 
	Ans lblk, rblk, row, col;
	for (int i = n + 2; i <= tgt; ++i)
		lblk.xs.push_back(i);
	for (int i = 1; i <= n; ++i)
		lblk.ys.push_back(i);
	if (!lblk.empty())
		ans.push_back(lblk);
 
	for (int i = 1; i <= n; ++i)
		rblk.xs.push_back(i);
	for (int i = n + 2; i <= tgt; ++i)
		rblk.ys.push_back(i);
	if (!rblk.empty())
		ans.push_back(rblk);
 
	row.xs.push_back(n + 1);
	for (int i = 1; i <= tgt; ++i)
		if (i != n && i != n + 1)
			row.ys.push_back(i);
	if (!row.empty())
		ans.push_back(row);
 
	for (int i = 1; i <= tgt; ++i)
		if (i != n + 1 && i != n + 2)
			col.xs.push_back(i);
	col.ys.push_back(n + 1);
	if (!col.empty())
		ans.push_back(col);
}
 
int main () {
	// freopen("out", "w", stdout);
 
	int n;
	scanf("%d", &n);
	// n = 5000;
	
	int i = 2;
	auto ans = std::vector<Ans>();
	ans.push_back(Ans { {1}, {2} });
	while (i < n) {
		dup(ans, i, n);
		i = std::min(i * 2 + 1, n);
	}
	
	printf("%d\n", (int)ans.size());
	for (auto &c: ans) {
		printf("%d", (int)c.xs.size());
		for (auto &x: c.xs)
			printf(" %d", x);
		printf("\n%d", (int)c.ys.size());
		for (auto &y: c.ys)
			printf(" %d", y);
		putchar('\n');
	}
 
	// fprintf(stderr, "%d\n", (int));
	return 0;
}

N

虽然确实很傻逼但是有坑(,不能随便把一个连通块的某条边改过去,因为有可能不小心改了桥边x

#include <cstdio>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <utility>
 
struct Graph {
	struct E {
		int idx;
		int to;
	};
 
	int n;
	std::vector<std::vector<E>> to;
	std::vector<int> vis;
	std::vector<int> eind, ind;
 
	Graph (int n_): n(n_), to(n), vis(n, -1), eind(n, -1), ind(n, 0) {}
 
	void adde (int idx, int a, int b) {
		to[a].push_back(E { idx, b });
		++ind[b];
		eind[b] = idx;
		// fprintf(stderr, "%d -> %d\n", a, b);
	}
 
	struct Ans {
		int idx;
		int from, to;
	};
 
	Ans dfs (int c, int fa, int ibeg) {
		// fprintf(stderr, "in (c=%d fa=%d ibeg=%d)\n", c, fa, ibeg);
 
		vis[c] = ibeg;
		Ans ret = { -1, -1, -1 };
		for (auto &e: to[c]) {
			//fprintf(stderr, "e> to=%d\n", e.to);
			if (e.to == fa) {
				fa = -1;
			} else if (vis[e.to] == ibeg) {
				ret = { e.idx, e.to, 0 };
			} else if (vis[e.to] == -1) {
				auto nxt = dfs(e.to, c, ibeg);
				if (ret.idx == -1) {
					ret = nxt;
				}
			}
		}
 
		//fprintf(stderr, "ret (c=%d) %d %d %d\n", c, ret.idx, ret.from, ret.to);
		return ret;
	}
 
	std::vector<Ans> solve () {
		int ifst = 0;
		dfs(0, -1, 0);
 
		auto blks = std::vector<Ans>(n, Ans { -1, -1, -1 });
		for (int i = 1; i < n; ++i)
			if (vis[i] == -1) {
				auto cur = dfs(i, -1, i);
				//fprintf(stderr, ">1 i=%d %d %d\n", i, cur.idx, cur.from);
				if (cur.idx == -1)
					blks[i].idx = -2;
				else
					blks[i] = cur;
			}
 
		/*&
		for (int i = 0; i < n; ++i)
			fprintf(stderr, "(%d,%d) ", blks[i].idx, blks[i].from);
		fprintf(stderr, " <<blks\n");
		for (int i = 0; i < n; ++i)
			fprintf(stderr, "%d ", vis[i]);
		fprintf(stderr, " <<vis\n");
		for (int i = 0; i < n; ++i)
			fprintf(stderr, "%d ", ind[i]);
		fprintf(stderr, " <<ind\n");
		for (int i = 0; i < n; ++i)
			fprintf(stderr, "%d ", eind[i]);
		fprintf(stderr, " <<eind\n");
		*/
 
		for (int i = 1; i < n; ++i)
			if (vis[i] >= 1 && ind[i] == 1 && blks[vis[i]].idx == -2) {
				//fprintf(stderr, ">2 %d %d\n", eind[i], i);
				blks[vis[i]] = { eind[i], i, ifst };
			}
 
		auto ret = std::vector<Ans>();
		for (auto &c: blks)
			if (c.idx != -1)
				ret.push_back(c);
		return ret;
	}
};
 
int main () {
	int t;
	scanf("%d", &t);
 
	while (t--) {
		int m;
		scanf("%d", &m);
		
		auto hm = std::vector<int>();
		auto es = std::vector<std::pair<int, int>>(m);
		for (auto &e: es) {
			scanf("%d%d", &e.first, &e.second);
			hm.push_back(e.first);
			hm.push_back(e.second);
		}
		std::sort(hm.begin(), hm.end());
		hm.erase(std::unique(hm.begin(), hm.end()), hm.end());
 
		auto g = Graph(hm.size());
 
		for (int i = 0; i < (int)es.size(); ++i) {
			int a = std::lower_bound(hm.begin(), hm.end(), es[i].first) - hm.begin();
			int b = std::lower_bound(hm.begin(), hm.end(), es[i].second) - hm.begin();
			g.adde(i, a, b);
			g.adde(i, b, a);
		}
 
		auto ans = g.solve();
		printf("%d\n", (int)ans.size());
		for (auto &c: ans) {
			int a = hm[c.from], b = hm[c.to];
			printf("%d %d %d\n", c.idx + 1, a, b);
		}
	}
 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值