Educational Codeforces Round 94 (Rated for Div. 2)

11 篇文章 0 订阅
1 篇文章 0 订阅

A - String Similarity
可以发现,string里面的最后一位每一次都会被遍历到,所以将res全部变成最后一位即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int T, n;
char s[101];
int main() {
	T = read();
	while (T--) {
		n = read();
		cin >> s;
		char c = s[n - 1];
		upd(i, 0, n - 1)printf("%c", c);
		cout << endl;
	}
	return 0;
}

B - RPG Protagonist
贪心。枚举一个人选取的S或者W,那么另外一个就可以贪心的计算出来。
对于另外一个人而言,他应该优先选取更小的那一个。还需要动态维护两个数量。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int T;
ll p, f;
ll cnts, cntw;
ll s, w;
int main() {
	T = read();
	while (T--) {
		p = read(), f = read();
		if (p < f)swap(p, f);
		cnts = read(), cntw = read();
		s = read(), w = read();
		if (s > w) {
			swap(cnts, cntw);
			swap(s, w);
		}
		ll ans = 0;
		upd(i, 0, cnts) {
			ll need = i * s;
			if (need > p)break;
			ll temp = i;
			ll temp2 = (p - need) / w;
			temp += temp2;
			ll temp3 = min(f / s, cnts - i);
			ll temp4 = min(cntw - temp2, (f - temp3 * s) / w);
			temp += temp3 + temp4;
			ans = max(ans, temp);
		}
		cout << ans << endl;
	}
	return 0;
}

C - Binary String Reconstruction
关注答案字符串中0的位置,他只能由左右两边同时为0构成。所以我们优先处理0的位置,并且将其他剩余位置全部赋值成1。最后在计算一次是否符合题意。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e5 + 10;
int T;
int x;
char s[N];
char res[N];
bool check(int n) {
	upd(i, 1, n) {
		if (s[i] == '1') {
			bool flag1 = 0;
			if (i - x >= 1) {
				if (res[i - x] == '1')flag1 = 1;
			}
			if (i + x <= n)if (res[i + x] == '1')flag1 = 1;
			if (flag1 == 0)return 0;
		}
	}
	return 1;
}
int main() {
	T = read();
	while (T--) {
		int n;
		scanf("%s", s + 1);
		n = strlen(s + 1);
		upd(i, 0, n)res[i] = 0;
		x = read();
		upd(i, 1, n) {
			if (s[i] == '0') {
				res[max(0, i - x)] = '0';
				res[min(n + 1, i + x)] = '0';
			}
		}
		upd(i, 1, n)if (res[i] == 0)res[i] = '1';
		res[n + 1] = '\0';
		if (check(n)) {
			printf("%s\n", res + 1);
		}
		else printf("%d\n", -1);
	}
}

D - Zigzags
枚举 i i i j j j,题目转换成找到 k < l , a [ k ] = a [ i ] , a [ j ] = a [ l ] k<l,a[k]=a[i],a[j]=a[l] k<l,a[k]=a[i],a[j]=a[l]。所以我们需要高效的查询, j j j位置后面,满足题意的 p a i r ( k , l ) pair(k,l) pair(k,l)的数量。
s u m [ i ] [ j ] sum[i][j] sum[i][j]表示 a [ i ′ ] = = i , a [ j ′ ] = = j a[i']==i,a[j']==j a[i]==i,a[j]==j有多少对满足题意,我们从后往前枚举,不断维护该数组,就可以找到满足题意的 p a i r pair pair。所以我们需要先预处理出,对于位置 i i i来说,( n x t [ i ] [ a [ j ′ ] ] nxt[i][a[j']] nxt[i][a[j]]表示 i i i后面值为 a [ j ′ ] a[j'] a[j] i i i后面接的数字的数量。那么每一次转移就有: s u m [ a [ i + 1 ] ] [ j ] + = n x t [ i + 1 ] [ j ] sum[a[i+1]][j]+=nxt[i+1][j] sum[a[i+1]][j]+=nxt[i+1][j]

																						  #include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 3e3 + 10;
int T, n;
ll a[N];
ll nxt[N][N];
ll suf[N][N];
int main() {
	T = read();
	while (T--) {
		n = read();
		upd(i, 0, n + 1)upd(j, 0, n + 1)nxt[i][j] = suf[i][j] = 0;
		upd(i, 1, n)a[i] = read();
		dwd(i, n, 1) {
			upd(j, 1, 3000) {
				nxt[i][j] = nxt[i + 1][j];
			}
			nxt[i][a[i + 1]]++;
		}
		ll ans = 0;
		dwd(i, n-1, 1) {
			upd(j, 1, 3000)
				suf[a[i + 1]][j] += nxt[i + 1][j];
			dwd(j, i - 1, 1) {
				ans += suf[a[j]][a[i]];
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

E - Clear the Multiset
如果对于一段区间 l , r l,r l,r,我们采用了操作1(整体减少1),那么一定会将最小值减少到0。不然的话不会比操作二更优秀。
所以我们发现,对于一段 l , r l,r l,r而言,答案最多是 r − l + 1 r-l+1 rl+1。进行操作1,将区间某一些位置变成0,这个时候我们得到了一些分开的单独的区间,利用分治,我们继续进入区间进行计算即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e3 + 10;
int a[N];
int n;
int dp(int l, int r) {
	if (r < l)return 0;
	int mn = 1e9 + 1;
	int pos = 0;
	upd(i, l, r)
	{
		if (mn > a[i]) {
			mn = a[i]; pos = i;
		}
	}
	upd(i, l, r)a[i] -= mn;
	return min(dp(l, pos - 1) + dp(pos + 1, r) + mn, r - l + 1);
}
int main() {
	n = read();
	upd(i, 1, n) {
		a[i] = read();
	}
	cout<<dp(1, n);
}

F - x-prime Substrings
预处理出,是x-prime的所有字符串。可以通过打表发现,最多2500个。插入到trie数中,最多10000个点。
题目转换成,给出一些字符串,在原串不能出现这些字符串。这就和ac自动机的一些裸题很类似了。(构建 t r i e trie trie图)
d p [ i ] [ j ] dp[i][j] dp[i][j]表示,做到原字符串第 i i i位,在 t i r e tire tire图上 j j j状态的最小代价。( t r i e trie trie图上任意状态都有转移状态)
如果有删除
d p [ i + 1 ] [ j ] = m i n ( d p [ i + 1 ] [ j ] , d p [ i ] [ j ] + 1 ) dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1) dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)
没有删除,并且下一个状态不是非法状态
d p [ i + 1 ] [ j ′ ] = m i n ( d p [ i + 1 ] [ j ′ ] , d p [ i ] [ j ] ) ( j ′ = t i r e . c h [ j ] [ s [ i ] − ′ 0 ] ) dp[i+1][j']=min(dp[i+1][j'],dp[i][j])(j'=tire.ch[j][s[i]-'0]) dp[i+1][j]=min(dp[i+1][j],dp[i][j])(j=tire.ch[j][s[i]0])

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1010;
vector<int>vec;
char s[N];
int x;
struct trie {
	int ch[N * 10][15];
	int flag[N * 10];
	int fail[N * 10];
	int cnt = 0;
	void insert() {
		/*for (auto k : vec)cout << k;
		cout << endl;*/
		int len = vec.size();
		int root = 0;
		up(i, 0, len) {
			int c = vec[i];
			if (!ch[root][c])
				ch[root][c] = ++cnt;
			root = ch[root][c];
		}
		//cout << this->cnt << endl;
		flag[root] = 1;
	}
	void getfail() {
		int root = 0;
		fail[root] = -1;
		queue<int>q;
		up(i, 0, 10)
			if (ch[root][i])q.push(ch[root][i]);
		while (!q.empty()) {
			int top = q.front();
			q.pop();
			up(i, 0, 10) {
				int v = ch[top][i];
				if (!v)ch[top][i] = ch[fail[top]][i];
				else {
					q.push(v);
					fail[v] = ch[fail[top]][i];
					flag[v] |= flag[fail[v]];
				}
			}
		}
	}
}T;
void dfs(int sum) {
	if (sum > x)return;
	if (sum == x) {
		up(i, 0, vec.size()) {
			int summ = 0;
			dwd(j, i, 0) {
				summ += vec[j];
				if (summ != x) {
					if (x%summ == 0)return;
				}
			}
		}
		T.insert();
		return;
	}
	upd(i, 1, 9) {
		vec.push_back(i);
		dfs(sum + i);
		vec.pop_back();
	}
}
int dp[N][N * 10];
void test(int n) {
	cout << T.cnt << endl;
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= T.cnt; ++j) {
			printf("%d ", dp[i][j]);
		}
		cout << endl;
	}
}
int main() {
	cin >> s;
	x = read();
	dfs(0);
	T.getfail();
	int n = strlen(s);
	memset(dp, INF, sizeof(dp));
	dp[0][0] = 0;
	up(i, 0, n) {
		upd(j, 0, T.cnt) {
			if (dp[i][j]>=INF)continue;
			dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 1);
			int c = T.ch[j][s[i] - '0'];
			if (T.flag[c])continue;
			dp[i + 1][c] = min(dp[i + 1][c], dp[i][j]);
		}
	}
	int ans = INF;
	//test(n);
	upd(j, 0, T.cnt)
		ans = min(ans, dp[n][j]);
	cout << ans << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值