首页 > 其他分享 >AtCoder Beginner Contest 283 A-F 题解

AtCoder Beginner Contest 283 A-F 题解

时间:2023-02-24 22:44:27浏览次数:34  
标签:tmp AtCoder return int 题解 res ans 283 include

A - Power

快速幂板子

点击查看代码
#include<cstdio>
#include<algorithm>
using namespace std;

#define int long long

int n, m;

int qpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res *= a;
		a *= a, b >>= 1;
	}
	return res;
}

signed main() {
	scanf("%lld %lld", &n, &m);
	printf("%lld", qpow(n, m));
	return 0;
}

B - First Query Problem

跟着模拟就好,该修改就修改,该输出就输出。

点击查看代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5;
//#define int long long

int n, m, a[N];

int qpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res *= a;
		a *= a, b >>= 1;
	}
	return res;
}

signed main() {
	
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	scanf("%d", &m);
	int op, x, y;
	while(m --) {
		scanf("%d", &op);
		if(op == 1) {
			scanf("%d %d", &x, &y);
			a[x] = y;
		}
		else scanf("%d", &x), printf("%d\n", a[x]);
	}
	return 0;
}

C - Cash Register

倒着处理,如果数字为 1 ~ 9,加 1,

判断是否有 00,如果有,只加 1。

点击查看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5 + 5;
//#define int long long

int n, ans, a[N];

int qpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res *= a;
		a *= a, b >>= 1;
	}
	return res;
}

char s[N];

signed main() {
	
	scanf("%s", s + 1);
	n = strlen(s + 1);
	
	for(int i = n; i; i --) {
		if(i > 1 && s[i] == s[i - 1] && s[i] == '0') i --;
		ans ++;
	}
	printf("%d", ans);
	return 0;
}

D - Scope

因为题目保证输入字符串为合法,所以预处理出每个左右括号匹配的区间,st[i] ~ ed[i] (表示 s[i] 为 '(' 时的匹配区间)

因为是从左到右处理过来的,所以在 i 之前的括号区间肯定都处理过,因此可以直接跳过,

再拿个 bool 数组记录一下字母是否出现,完了。

点击查看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 3e5 + 5;
//#define int long long

int n, ans, a[N], st[N], ed[N], top, sta[N];

char s[N];

bool vis[N], tag[N];

signed main() {
	
	scanf("%s", s + 1);
	n = strlen(s + 1);
	for(int i = 1; i <= n; i ++) {
		if(s[i] == '(' ) sta[++top] = i;
		if(s[i] == ')') {
			ed[sta[top]] = i;
			st[i] = sta[top];
			top --;
		}
	}
	
	for(int i = 1; i <= n; i ++) {
		if(s[i] != '(' && s[i] != ')') {
			if(vis[s[i] - 'a']) {
				puts("No");
				return 0;
			}
			vis[s[i] - 'a'] = 1;
		}
		else if(s[i] == ')'){
			for(int j = st[i] + 1; j <= i; j ++) {
				while(ed[j] && j <= i) j = ed[j] + 1;
				if(j > i) break;
				if(s[j] != '(' && s[j] != ')') vis[s[j] - 'a'] = 0;
			}
		}
	}
	puts("Yes");
	return 0;
}

E - Don't Isolate Elements

操作每次处理的是一行,因为每行有两种状态,A[i][j] or 1 - A[i][j]

分析可知,每行的可行性只与上下相邻的两行有关,

因此,定义状态 dp[i][j(0/1)][k(0/1)] 为 第 i - 1 行为 j 状态, 第 i 行为 k 状态时满足题意的最小操作数。

不难得出,dp[i][j][k] = min(dp[i - 1][h][j] + k) (h 为枚举的 i - 2 行的状态)

但需要判断三行状态为 h,j,k 时的合法性,

所以还要再写一个 check() 函数,特别注意 第 1 行 和 第 n 行的特殊性,需要单独判断、

点击查看代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
//#define int long long

int n, m, ans = 1e9, s[N][N];

int dp[N][2][2];

bool check(int d, int now, int low, int up) {
	int tmp;
	if(d == 1) {
		for(int i = 1; i <= m; i ++) {
			tmp = 0;
			if((s[d][i] ^ now) == (s[d + 1][i] ^ low)) tmp ++;
			if(i > 1 && s[d][i] == s[d][i - 1]) tmp ++;
			if(i < m && s[d][i] == s[d][i + 1]) tmp ++;
			if(!tmp) return 0;
		}
		return 1;
	}
	for(int i = 1; i <= m; i ++) {
		tmp = 0;
		if((s[d][i] ^ now) == (s[d + 1][i] ^ low) || (s[d][i] ^ now) == (s[d - 1][i] ^ up)) tmp ++;
		if(i > 1 && s[d][i] == s[d][i - 1]) tmp ++;
		if(i < m && s[d][i] == s[d][i + 1]) tmp ++;
		if(!tmp) return 0;
	}
	if(d == n - 1) {
		for(int i = 1; i <= m; i ++) {
			tmp = 0;
			if((s[n][i] ^ low) == (s[d][i] ^ now)) tmp ++;
			if(i > 1 && s[n][i] == s[n][i - 1]) tmp ++;
			if(i < m && s[n][i] == s[n][i + 1]) tmp ++;
			if(!tmp) return 0;
		}
	}
	return 1;
}

signed main() {
	
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= m; j ++)
			scanf("%d", &s[i][j]);
	}
	memset(dp, 0x3f, sizeof(dp));
	dp[1][0][0] = dp[1][1][0] = 0, dp[1][1][1] = dp[1][0][1] = 1;
	
	for(int i = 2; i <= n; i ++) {
		for(int a = 0; a < 2; a ++) {
			for(int b = 0; b < 2; b ++) {
				for(int c = 0; c < 2; c ++) {
					if(!check(i - 1, a, b, c)) continue;
					dp[i][a][b] = min(dp[i][a][b], dp[i - 1][c][a] + b);
				}
			}
		}
	}
	for(int i = 0; i < 2; i ++) {
		for(int j = 0; j < 2; j ++) {
			ans = min(dp[n][i][j], ans);
		}
	}
	
	if(ans == 1e9) puts("-1");
	else printf("%d",ans);
	
	return 0;
}

F - Permutation Distance

考虑把绝对值去掉,并且将 \(P_i\) 和 \(i\) , \(P_j\) 和 \(j\) 分别放到一边。

那么就需要分类讨论:

  • \(P_i + i + min(-P_j - j) (P_i > P_j, i > j)\)
  • \(P_i - i + min(-P_j + j) (P_i > P_j, i < j)\)
  • \(-P_i + i + min(P_j - j) (P_i < P_j, i > j)\)
  • \(-P_i - i + min(P_j + h) (P_i < P_j, i < j)\)

于是问题就转化为求两个不等关系条件下的最小值(二维偏序),

我们就可以循环 \(i \in [1, n]\) 来控制一个不等条件,另一个条件用数据结构维护(线段树——单点修改,区间查询)。

即可求出最值。

点击查看代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 2e5 + 5, inf = 1e9;

struct node {
	int l, r, a, b;
	node(){}
	node(int L, int R, int A, int B) {
		l = L, r = R, a = A, b = B;
	}
}tr[N << 4];

int n, A[N];

#define ls k << 1
#define rs k << 1 | 1

void pushup(int k) {
	tr[k].a = min(tr[ls].a, tr[rs].a);
	tr[k].b = min(tr[ls].b, tr[rs].b);
}

node merge(node x, node y) {
	node res = node(x.l, y.r, min(x.a, y.a), min(y.b, x.b));
	return res;
} 

node query(int k, int st, int ed) {
	if(tr[k].l >= st && tr[k].r <= ed) return tr[k];
	int mid = (tr[k].l + tr[k].r) >> 1;
	node res;
	if(ed <= mid) return query(ls, st, ed);
	else if(st > mid) return query(rs, st, ed);
	else return merge(query(ls, st, ed), query(rs, st, ed)); 
}

void change(int k, int pos, int a, int b) {
	if(tr[k].l == tr[k].r) {
		tr[k].a = a, tr[k].b = b;
		return;
	}
	int mid = (tr[k].l + tr[k].r) >> 1;
	if(pos <= mid) change(ls, pos, a, b);
	else change(rs, pos, a, b);
	pushup(k);
}

void build(int k, int l, int r) {
	if(l == r) {
		tr[k] = node(l, r, inf, inf);
		return;
	}
	tr[k].l = l, tr[k].r = r;
	int mid = (l + r) >> 1;
	build(ls, l, mid), build(rs, mid + 1, r);
	pushup(k);
}
int ans[N];
int main() {
	scanf("%d", &n);
	memset(ans, 0x3f, sizeof(ans));
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &A[i]);
	}
	build(1, 1, n);
//	puts("*2");
	for(int i = 1; i <= n; i ++) {
		if(A[i] > 1) ans[i] = min(ans[i], A[i] + i + query(1, 1, A[i] - 1).a);
		if(A[i] < n) ans[i] = min(ans[i], i - A[i] + query(1, A[i] + 1, n).b);
		change(1, A[i], - A[i] - i, A[i] - i);
		
	}
	build(1, 1, n);
	for(int i = n; i; i --) {
		if(A[i] > 1) ans[i] = min(ans[i], A[i] - i + query(1, 1, A[i] - 1).a);
		if(A[i] < n) ans[i] = min(ans[i], - i - A[i] + query(1, A[i] + 1, n).b);
		change(1, A[i], - A[i] + i, A[i] + i);
	}
	for(int i = 1; i <= n; i ++) printf("%d ", ans[i]);
	return 0;
}

标签:tmp,AtCoder,return,int,题解,res,ans,283,include
From: https://www.cnblogs.com/Spring-Araki/p/17153436.html

相关文章

  • CF837D题解
    CF837D题解没有用的话今天晚上在CF题库里随便选题选的,感觉还不错的题。昨天就开始停自习了,但是一直在摆烂(悲,自从上个学期就这样了,非常怀念一年前的机房,风清气正,大家都......
  • THUPC2019 令人难以忘记的题目名称 题解
    首先感性感觉这个东西是比较有循环节的,但这是后话。最后几步一定是差分相同->每个数相同->全为0。不平凡地猜想差分\(k\)次全\(0\)等价于可以\(k\)步胜利。假设......
  • Universial Cup 题解
    开始瞎做题了全部都写了简要题意,题解默认折叠,可以来做做(?UniversialCup官网The1stUniversalCup比赛名称&题解链接题解包含题目QOJlinkCodeforcesGymLin......
  • loj2839
    除了L神txdy我还能说啥呢。(L神把这题搬模拟赛了。。。)即把每个x换成(或),问是否能通过不多于一次区间反转((与)交换)后合法。考虑怎样的括号串是合法的。假设......
  • 题解 北大集训2018 点分治
    题意给定\(n\)个点的树,求点分治方案数,对\(10^9+7\)取模。两种方案不同当且仅当点分树不同。\(1\leqn\leq5000\)题解考虑怎样合并两个点分治方案。如果我们有......
  • history 题解(并查集)
    考虑使用边带权并查集维护点之间的连通性,边权为这条边建立的时间,查询时如果查询时间小于边权则不能通行(巧妙地处理了时间的性质)。由于时间这种东西性质特殊无法路径压缩,所......
  • 新版 Mac M2 安装老 saas 项目 报 Gem sass is not installed 问题解决
     换了新电脑,需要把老项目git拉下来再跑起来的时候发现生成样式文件的时候会报这个错误,(N年前老项目,用的是node-sass,[email protected]版本比较老旧,但项目还是要......
  • vue——更改路由模式为history后,刷新页面显示Cannot Get/空白/404,本地icon图标不显示
    参考:https://blog.csdn.net/william_jzy/article/details/106526339   https://www.bbsmax.com/A/A7zgKEVkz4/      https://router.vuejs.org/zh/gu......
  • CF1131B 题解
    题目传送门好水的绿题,当放松了。题目分析为了方便表述,定义\(lsta,lstb,nowa,nowb\),分别表示上次双方的得分以及当前的得分。考虑分讨,若\(lsta=lstb\),贡献即\(\min(n......
  • P6666 [清华集训2016] 数据交互 题解
    ##P6666[清华集训2016]数据交互题解###简要题意:n个点的树,m次操作,分别为添加一条路径$(u_i,v_i,w_i)$,和撤消一条路径,每一次操作后求出一条路径使得与这条路径有交的......