2023冲刺国赛模拟5

A. 无限之环

不难发现 \(B\) 需要字母集合相同

对于 \(A\) ,需要最后一个 \(B\) 中未出现的字母前完全相同

这里写的用了 \(string\)

实际上为了复杂度的话应该用 \(hash\)

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<string, int> psi;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 1e5 + 55;
int n, cnt;
map<psi, int>mp;
vector<int>ans[maxn];
string a, b;
void print(){
	printf("%d\n",cnt);
	for(int i = 1; i <= cnt; ++i){
		printf("%d ",(int)ans[i].size());
		for(int v : ans[i])printf("%d ",v); printf("\n");
	}
}
bool vis[maxn];
int main(){
	freopen("infty.in","r",stdin);
	freopen("infty.out","w",stdout);
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; ++i){
		cin >> a >> b; psi res;
		int len = b.size(), s = 0;
		if(len == 1 && b[0] == '=')--len;
		for(int j = 0; j < len; ++j)s |= (1 << (b[j] - 'a'));
		res.second = s;
		len = a.size();
		if(len == 1 && a[0] == '=')res.first = "";
		else{
			while(len && (s & (1 << (a[len - 1] - 'a'))))--len;
			string tmp = ""; for(int j = 0; j < len; ++j)tmp += a[j];
			res.first = tmp;
		}
		if(!mp[res])mp[res] = ++cnt;
		ans[mp[res]].push_back(i);
	}
	print();
	return 0;
}

B. 变化多端

搜索。。。

如果马多就移动空格

一种可能的实现是按照顺序枚举马槽,然后搜到马移动

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
vector<pair<pii, pii>>ans;
int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1}, dy[8] = {2, 1, -1, -2, -2, -1, 1, 2};
int n; char s[5];
bool mp[9][9], vis[9][9];
vector<pii>v; 
pii pre[9][9];
void move(int ax, int ay, int bx, int by){
	swap(mp[ax][ay], mp[bx][by]);
	ans.push_back({pii(ax, ay), pii(bx, by)});
}
int rx, ry;
bool dfs(int x, int y){
	vis[x][y] = true;
	if(mp[x][y]){rx = x; ry = y; return true;}
	for(int i = 0; i < 8; ++i){
		int nx = x + dx[i], ny = y + dy[i];
		if(nx >= 1 && nx <= 8 && ny >= 1 && ny <= 8 && !vis[nx][ny]){
			pre[nx][ny] = {x, y};
			if(dfs(nx, ny))return true;
		}
	}
	return false;
}
void trans(int i, int j){
	v.push_back(pii(i, j));
	if(mp[i][j])return;
	memset(vis, 0, sizeof(vis));
	for(pii x : v)vis[x.first][x.second] = 1;
	rx = ry = 0; dfs(i, j);
	if(rx){
		while(rx != i || ry != j){
			int tx = pre[rx][ry].first, ty = pre[rx][ry].second;
			move(rx, ry, tx, ty);
			rx = tx; ry = ty;
		}
	}
}
int main(){
	freopen("changeful.in","r",stdin);
	freopen("changeful.out","w",stdout);
	n = read();
	for(int i = 1; i <= n; ++i){
		scanf("%s",s); 
		mp[s[1] - '0'][s[0] - 'a' + 1] = true;
	}
	if(n <= 32){
		for(int i = 1; i <= 8; ++i)
			for(int j = 1; j <= 8; ++j)
				trans(i, j);
		printf("%d\n",(int)ans.size());
		for(pair<pii, pii> v : ans)printf("%c%d-%c%d\n",v.first.second + 'a' - 1, v.first.first, v.second.second + 'a' - 1, v.second.first);
	}else{
		for(int i = 1; i <= 8; ++i)
			for(int j = 1; j <= 8; ++j)
				mp[i][j] ^= 1;
		for(int i = 8; i >= 1; --i)
			for(int j = 8; j >= 1; --j)
				trans(i, j);
		printf("%d\n",(int)ans.size());
		for(pair<pii, pii> v : ans)printf("%c%d-%c%d\n",v.second.second + 'a' - 1, v.second.first, v.first.second + 'a' - 1, v.first.first);
	}
	return 0;
}

C. 活罪难赦

性质的分析

二进制按位考虑

区间修改转查分

。。。

image

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 3e5 + 55, lg = 20;
int n, q, sum[lg][maxn], a[maxn]; char s[maxn];
int main(){
	freopen("sins.in","r",stdin);
	freopen("sins.out","w",stdout);
	scanf("%d%s%d",&n, s, &q);
	for(int i = 1; i < n; ++i)a[i] = s[i] ^ s[i - 1];
	for(int i = 0; (1 << i) <= n; ++i){
		int len = 1 << (i + 1);
		for(int j = 1; j < len; ++j)sum[i][j] = a[j];
		for(int j = len; j <= n; ++j)sum[i][j] = sum[i][j - len] + a[j];
	}
	for(int i = 1; i <= q; ++i){
		int l = read(), r = read();
		int ans = 0;
		for(int j = 0; (1 << j) < (r - l + 1); ++j){
			int cnt = (r - l + 1) >> (j + 1);
			int c1 = sum[j][r - (1 << j) + 1];
			if(l >= (1 << j))c1 -= sum[j][l - (1 << j)];
			ans += min(c1, cnt - c1);
		}
		printf("%d\n",(ans + 1) >> 1);
	}
}
posted @ 2023-05-26 20:23  Chen_jr  阅读(13)  评论(0编辑  收藏  举报