Codeforces Round #610 (Div. 2) 题解

Temporarily unavailable

\[Time Limit: 1 s\quad Memory Limit: 256 MB \]

直接计算出 \([c-r, c+r]\)\([a, b]\) 中的范围有多大,然后减掉就可以了。

view
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

int main() {
	scanf("%d", &T);
	while(T--) {
		ll a, b, c, r, ans;
		scanf("%lld%lld%lld%lld", &a, &b, &c, &r);
		if(a>b)	swap(a, b);
		ans = b-a;
		ll over = max(a, min(c+r, b)) - min(b, max(c-r, a));
		printf("%lld\n", ans-over);
	}
	return 0;
}

K for the Price of One (Hard Version)

\[Time Limit: 2 s\quad Memory Limit: 256 MB \]

首先肯定是买最便宜的,由于有 \(k\) 个只能买 \(k\) 个,所以可以看成有两种策略,买 \(1\) 个和买 \(k\) 个,然后用 \(dp[i]\) 表示买了前 \(i\) 个物品的最少花费,然后看给出的钱可以买多少个。

view
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
 
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;
 
int n, m, k;
int cas, tol, T;
 
ll dp[maxn];
int a[maxn];
 
int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d%d", &n, &m, &k);
		for(int i=1; i<=n; i++)	scanf("%d", &a[i]);
		for(int i=1; i<=n; i++)	dp[i] = INF;
		dp[0] = 0;
		sort(a+1, a+1+n);
		for(int i=1; i<=n; i++) {
			if(i-k>=0)
				dp[i] = min(dp[i-1], dp[i-k])+a[i];
			else
				dp[i] = dp[i-1]+a[i];
		}
		ll ans = 0;
		for(int i=n; i>=1; i--) {
			if(dp[i] <= m) {
				ans = i;
				break;
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

Petya and Exam

\[Time Limit: 2 s\quad Memory Limit: 256 MB \]

由于有一个限制时间 \(t_i\),那么我可以按限制时间 \(t_i\) 排序来完成每一个作业。

\(p[i]\) 表示完成 \(i\) 个作业需要的时间,那么我想要完成这 \(i\) 个作业,我所用的时间必须在 \(t_{i+1}\) 以内,这些是必须要完成的作业。

接下来还有一部分剩下的时间,我可以用这些剩余的时间去贪心完成还没到达限制时间的作业,每次先完成简单的,在完成难的。

view
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>
 
typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 2e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;
 
ll n, m;
int cas, tol, T;

struct Node {
	ll a, b, p;
	bool operator < (Node c) const {
		return b<c.b;
	}
} node[maxn];
ll p[maxn], a[2];

ll solve(ll time, ll x, ll y) {
	ll cnt = 0;
	ll oka = min(x, time/a[0]);
	cnt += oka;
	time -= oka*a[0];
	ll okb = min(y, time/a[1]);
	cnt += okb;
	return cnt;
}

int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%lld%lld%lld%lld", &n, &m, &a[0], &a[1]);
		for(int i=1, x; i<=n; i++) {
			scanf("%lld", &node[i].p);
			node[i].a = a[node[i].p];
		}
		for(int i=1; i<=n; i++) {
			scanf("%lld", &node[i].b);
		}
		p[0] = 0;
		sort(node+1, node+1+n);
		node[n+1].b = m+1;
		for(int i=1; i<=n; i++)	p[i] = p[i-1]+node[i].a;
		ll ans = 0, cnt[2] = {0};
//		for(int i=1; i<=n; i++)	printf("%d%c", node[i].a, i==n ? '\n':' ');
//		for(int i=1; i<=n; i++)	printf("%d%c", node[i].b, i==n ? '\n':' ');
//		for(int i=1; i<=n; i++)	printf("%d%c", p[i], i==n ? '\n':' ');
//		cout << "=====" << endl;
		for(int i=n; i>=0; i--) {
			if(p[i] < node[i+1].b)
				ans = max(ans, i+solve(node[i+1].b-p[i]-1, cnt[0], cnt[1]));
			cnt[node[i].p]++;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

Enchanted Artifact

\[Time Limit: 1 s\quad Memory Limit: 256 MB \]

表示 \(D、E\) 题意一直都没读懂,所以这里也讲一下题意。

这是一题交互题,也就是一问一答的形式。题意想要让你猜一个全由 \(a、b\) 组成的字符串,每次你输出一个字符串,题目返回你的字符串和题目的字符串二者之间的编辑距离,要求最多只能问 \(n+2\) 次,并且每次询问的字符串长度不可以超过 \(300\)

第一次给出一个字符串 \(a\),获得它和答案字符串的编辑距离 \(n\)。考虑如下事情:如果答案字符串存在一个 \(a\),那么这个 \(a\) 一定不变化,只要在两侧插入其他字符即可,那么答案字符串长度就是 \(n+1\)。如果不存在一个 \(a\),那么这个 \(a\) 一定要通过一次操作变成 \(b\),然后在两侧加入其他字符,则答案字符串长度就是 \(n\)

那么第二步我可以输出长度为 \(n+1\) 并且全为 \(a\) 的字符,获得两者的编辑距离 \(m\),那么如果 \(m == n+1\),答案就一定是第二种,否则就一定是第一种。

此时我们就获得了答案字符串的字符长度和全为 \(a\) 时的编辑距离。所以此时的编辑距离可以理解成当前字符串和答案字符串 \(s[i] \neq t[i]\) 的个数。所以我只要操作每一位,把每一位从 \(a\) 换成 \(b\),看编辑距离会不会变小,就知道了这一位是不是和答案字符串相同了。

view
/*************************************************************** 
    > File Name        : e.cpp
    > Author           : Jiaaaaaaaqi
    > Created Time     : 2019/12/28 19:37:44
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

pii solve() {
	cout << "a" << endl;
	cin >> n;
	if(n == 300) {
		for(int i=1; i<=300; i++)	cout << "b";
		cout << endl;
		exit(0);
	}
	string ans = "";
	for(int i=0; i<=n; i++)	ans += 'a';
	cout << ans << endl;
	cin >> m;
	if(m == n+1) {
		for(int i=1; i<=n; i++)	cout << "b";
		cout << endl;
		exit(0);
	} else {
		return {n+1, m};
	}
}

int main() {
	// freopen("in", "r", stdin);
	pii pa = solve();
	int len = pa.fi, ans = pa.se;
	string ask;
	for(int i=1; i<=len; i++)	ask += 'a';
	for(int i=0; ans&&i<len; i++) {
		ask[i] = 'b';
		cout << ask << endl;
		cin >> n;
		if(n < ans)	ans = n;
		else	ask[i] = 'a';
	}
	cout << ask << endl;
	return 0;
}

The Cake Is a Lie

\[Time Limit: 2 s\quad Memory Limit: 256 MB \]

把一个 \(n\) 边形割成 \(n-2\) 个三角形,给出这 \(n-2\) 个三角形三个顶点标号,让你构造出 \(p、q\) 数组,\(p\) 数组表示这个 \(n\) 边形顺时针或者逆时针走一圈各个点的标号,\(q\) 数组表示切割三角形的顺序。

分成两步来做,第一步确定这个 \(n\) 边形的标号。我们考虑 \(n\) 边形的 \(n\) 条边一定是在且只在一个三角形内,而通过切割后出现的边,则一定会使用两次。

那么把三角形的边存起来,然后看对于每一个顶点 \(u\),若存在一个从 \(u\)\(v\) 的边,则说明 \(u-v\) 这条边在一个三角形内出现过,那么只要找到每个 \(u\) 和其相连的且只出现一次的 \(v\),把 \(v\) 放在 \(u\) 两侧即可,然后通过 \(dfs\) 一个一个搜出来就可以了。

对于第二步更加简单,想要切下来一个三角形,那么这个三角形一定是两个边在最外侧,一个边还没切割出来,然后去切割这还没被切割出来的边,那么只要通过拓扑排序类似的方法来一个个切就可以了。

view
/*************************************************************** 
    > File Name        : e.cpp
    > Author           : Jiaaaaaaaqi
    > Created Time     : 2019/12/28 20:48:26
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

vector<int> g[maxn];
int p[maxn], q[maxn], pos[maxn];
bool vis[maxn];
struct E {
	int a, b, c, cnt;
} e[maxn];

void put(int u, int v) {
	if(pos[v])	return ;
	int x = pos[u], y;
	y = (x-1==0 ? n : x-1);
	if(!p[y]) {
		p[y] = v;
		pos[v] = y;
		return ;
	}
	y = (x+1==n+1 ? 1 : x+1);
	if(!p[y]) {
		p[y] = v;
		pos[v] = y;
		return ;
	}
}

void dfs(int u) {
	if(vis[u])	return ;
	vis[u] = true;
	for(int i=0, cnt=1; i<g[u].size()-1; i++) {
		if(g[u][i] == g[u][i+1])	cnt++;
		else {
			if(cnt == 1)	put(u, g[u][i]), dfs(g[u][i]);
			cnt = 1;
		}
	}
}

map<pii, int> mp, mp2;
vector<int> vv[maxn*10];

void topu() {
	queue<int> Q;
	int ans = 0;
	for(int i=1; i<=n; i++)	mp2[{min(p[i], p[i%n+1]), max(p[i], p[i%n+1])}] = 1;
	for(int i=1; i<=m; i++)	vis[i] = 0;
	for(int i=1; i<=m; i++) {
		e[i].cnt += mp2[{e[i].a, e[i].b}];
		e[i].cnt += mp2[{e[i].a, e[i].c}];
		e[i].cnt += mp2[{e[i].b, e[i].c}];
		if(e[i].cnt == 2)	Q.push(i);
	}
	while(!Q.empty()) {
		int u = Q.front();
		Q.pop();
		q[++ans] = u;
		vis[u] = 1;
		pii pa;
		if(!mp2[{e[u].a, e[u].b}])	pa = {e[u].a, e[u].b};
		if(!mp2[{e[u].a, e[u].c}])	pa = {e[u].a, e[u].c};
		if(!mp2[{e[u].b, e[u].c}])	pa = {e[u].b, e[u].c};
		mp2[{pa.fi, pa.se}] = 1;
		for(auto t : vv[mp[{pa.fi, pa.se}]]) {
			e[t].cnt++;
			if(e[t].cnt == 2)	Q.push(t);
		}
	}
	if(n==3)	q[++ans] = 1;
}

int main() {
	// freopen("in", "r", stdin);
	scanf("%d", &T);
	while(T--) {
		scanf("%d", &n);
		tol = 0, mp.clear(), mp2.clear();
		for(int i=1; i<=n; i++)	g[i].clear(), vv[i].clear();
		for(int i=1; i<=n; i++)	p[i] = q[i] = pos[i] = vis[i] = 0;
		for(int i=1; i<=n-2; i++) {
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			if(a>b)	swap(a, b);
			if(a>c)	swap(a, c);
			if(b>c)	swap(b, c);
			g[a].pb(b), g[a].pb(c);
			g[b].pb(a), g[b].pb(c);
			g[c].pb(a), g[c].pb(b);
			if(!mp.count({a, b}))	mp[{a, b}] = ++tol, vv[tol].clear();
			if(!mp.count({a, c}))	mp[{a, c}] = ++tol, vv[tol].clear();
			if(!mp.count({b, c}))	mp[{b, c}] = ++tol, vv[tol].clear();
			vv[mp[{a, b}]].pb(i);
			vv[mp[{a, c}]].pb(i);
			vv[mp[{b, c}]].pb(i);
			e[i] = {a, b, c, 0};
		}
		for(int i=1; i<=n; i++)	g[i].pb(n+1), sort(g[i].begin(), g[i].end());
		pos[1] = p[1] = 1, m = n-2;
		dfs(1);
		topu();
		for(int i=1; i<=n; i++)	printf("%d%c", p[i], i==n ? '\n':' ');
		for(int i=1; i<=m; i++)	printf("%d%c", q[i], i==m ? '\n':' ');
	}
	return 0;
}
posted @ 2019-12-25 22:30  Jiaaaaaaaqi  阅读(233)  评论(0编辑  收藏  举报