首页 > 其他分享 >Atcoder Regular Contest 147

Atcoder Regular Contest 147

时间:2022-09-05 11:57:02浏览次数:107  
标签:Atcoder return 147 int back Regular ans push query

 

Atcoder Regular Contest 147

这是本蒟蒻第3次打的 \(ARC\),赛时的时候 \(B\) 题调代码调崩了, \(wa\) 了15发。所以来简略的写一下题解

A:

题目链接

题目大意:略
题目分析:

对于区间查找最大最小,为什么不用线段树呢?

但是我们会发现对于修改的话,我们需要单点修改,而不知道下标,怎么解决呢?

我们可以用一个结构体记录下当前最大最小值的下标,可以方便以后的修改,具体实现看代码

代码实现:
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 2e5 + 7;
struct T {
	int val , id;	
	
}maxx[M << 2];
struct TT {
	int val , id;
}minn[M << 2];
int a[M];
void change(int k) {
	if(maxx[k << 1].val > maxx[k << 1 | 1].val) maxx[k] = maxx[k << 1];
	else maxx[k] = maxx[k << 1 | 1];
	if(minn[k << 1].val < minn[k << 1 | 1].val) minn[k] = minn[k << 1];
	else minn[k] = minn[k << 1 | 1];
}
void buildtree(int k , int l , int r) {
	if(l == r) {
		maxx[k] = {a[l] , l};
		minn[k] = {a[l] , l};
		return;	
	}
	int mid = l + r >> 1;
	buildtree(k << 1 , l , mid);
	buildtree(k << 1 | 1, mid + 1  , r);
	change(k);
}
void change(int k , int l , int r , int p , int x) {
	if(l == r) {
		if(x == 0)
		minn[k].val = 0x7fffffff;//当 maxx = 0 时,minn 应变为极大值
		else minn[k].val =x;
		maxx[k].val = x;
		return;
	}
	int mid = l + r >> 1;
	if(p <= mid) change(k << 1 , l , mid , p , x);
	else change(k << 1 | 1, mid + 1 ,r  , p, x);
	change(k);
}
T query_max(int k , int l , int r , int L , int R) {
	if(L > r || R < l) return {0 , 0};
	if(L <= l && R >= r) return maxx[k];
	int mid = l + r >> 1;
	T ans = query_max(k << 1 , l , mid , L , R);
	T anss = query_max(k << 1 , mid + 1 , r , L , R);
	if(ans.val > anss.val)
	return ans;
	else return anss;
}	
TT query_min(int k , int l , int r , int L , int R) {
	if(L > r || R < l) return {0x3f3f3f3f , 0};
	if(L <= l && R >= r) return minn[k];
	int mid = l + r >> 1;
	TT ans = query_min(k << 1 , l , mid , L , R);
	TT anss = query_min(k << 1 , mid + 1 , r , L , R);
	if(ans.val < anss.val)
	return ans;
	else return anss;
}	
signed main () {
	ios::sync_with_stdio(0),cin.tie(0);
	int n; cin >> n;
	for(int i = 1; i <= n; ++ i) {cin >> a[i];}
	buildtree(1 , 1,  n);
	int cnt = 0;//用于记录删除个数
	int ans = 0;
	while(cnt < n - 1) {
		T x = query_max(1 , 1 , n , 1 , n);
		TT y = query_min(1 , 1 , n , 1 , n);
		int xx = x.val;
		int yy = y.val;
		ans ++;
		if(xx % yy == 0) {
			cnt ++;
			change(1 , 1, n ,x.id, 0);
			continue;
		}
		change(1 , 1 , n , x.id ,(xx % yy) );
	}
	cout << ans;
}

[========]

B:

题目链接

题目大意:略
题目分析:
  • [\(1\)] : 因为题目中说要满足操作 \(A\) 次数最少,所以我们可以确定 \(A\) 的次数是固定的,那么我们仔细观察一下 \(A\) 操作在干嘛,他将 \(p_i\) 与 \(p_{i + 1}\) 进行了交换,也就是让他们所位于的位置的奇偶性发生了变化,那么这有什么用呢?我们再来观察 \(B\) 在干嘛? \(B\) 操作是将 \(p_i\) 与 \(p_{i + 2}\) 进行了交换,我们知道对于一个数 \(x\) , \(x\) 与 \(x + 2\) 的奇偶性相同。

  • [\(2\)] : 有了以上的分析,我们大概就知道的 \(A\) 的重要性,那么我们先猜一下 \(A\) 的操作次数,假设 \((p_i \& 1) \neq (i \& 1)\) 的数量 \(num\) , 那么 \(A\) 的操作次数为 \(\frac{num}{2}\)。

  • [\(3\)] : 那么下面我们来简单说明一下:因为操作 \(B\) 可以使奇偶性相同的下标的位置进行交换,那么我们只需要让 \((p_i \& 1) = (i \& 1)\) 即可.
    又因为只能用操作 \(A\) 来将 \((p_i \& 1) \neq (i \& 1)\) 变为该种情况,且如果存在一个 \((p_i \& 1) \neq (i \& 1)\) ,那么一定存在另一个 \(j\) , 满足 \((p_j \& 1) \neq (j \& 1)\),所以该种情况是成对出现的,所以我们只需要 \(\frac{num}{2}\) 次操作即可满足 : \(\forall i \in (1 , N)\) , \((p_i \& 1) = (i \& 1)\)

  • [\(4\)] : 那么满足 :\(\forall i \in (1 , N)\) , \((p_i \& 1) = (i \& 1)\) 之后 , 我们只需要将其从小到大排序即可

代码实现:

用两个 \(vector\) 来储存答案, 对于每次移动我们需要反向存答案,具体实现看代码

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M = 5e2 + 20;
int p[M];
vector<char> ans;
vector<int> sum;
signed main () {
	ios::sync_with_stdio(0),cin.tie(0);
	int n; cin >> n;
	for(int i = 1; i <= n; ++ i) {cin >> p[i];}
	for(int i = 1; i < n; ++ i) {
		if((i & 1) != (p[i] & 1)) {
			int k;
			for(int j = i; j  < n; j += 2) {
				if((p[j] & 1) == (i & 1)) {//这里一定要注意顺序,可以用B交换一定先用B
					k = j;
					break;	
				}
				if((i & 1) == (p[j + 1] & 1)) {//这里注意下标
					ans.push_back('A');
					sum.push_back(j);	
					swap(p[j] , p[j + 1]);
					k = j;
					break;
				}
				
			}
			while(k > i) {//因为是从后往前交换的,所以从后往前进行操作B
			ans.push_back('B');
			sum.push_back(k - 2);//一定是k - 2,因为交换 p_i 与 p_{i + 2}
			swap(p[k] , p[k - 2]);
			k -= 2;
			}
		}
	}
	for(int i = 1; i <= n - 2; ++ i) {
		if(i == p[i]) continue;
		int k = i;
		for(int j = i + 2; j <= n; j += 2) {
			if(p[j] == i) {//找到大小为 i 的数
				k = j;
				break;	
			}
		}
		while(k > i) { //将 大小为 i 的 p_k 放到 i 位置上
			ans.push_back('B');
			sum.push_back(k - 2);
			swap(p[k] , p[k - 2]);
			k -= 2;
		}
	}
	cout << ans.size() << '\n';
	for(unsigned i = 0; i < ans.size(); ++ i) {//直接输出即可
		cout << ans[i] << ' ' << sum[i] << '\n';	
	}
	
}

由于笔者太弱了,所以只能写两道题,这次比赛还算成功吧。

[========]

完结散花

标签:Atcoder,return,147,int,back,Regular,ans,push,query
From: https://www.cnblogs.com/Love-yx/p/16657404.html

相关文章

  • AtCoder Beginner Contest 267 解题报告
    A-Saturday题意:输入字符串代表周一至周五的某一天,输出这一天离周六还有多少天分析:映射一下,直接输入输出ac代码:#include<iostream>#include<algorithm>#inclu......
  • AtCoder Beginner Contest 267
    E-ErasingVertices2做法1观察可得:对于某个时刻,贪心删当前代价最小的点肯定是最优的。但是删一个点会减少相邻接的点的代价。然后就想到了堆,但是这个堆需要支持decre......
  • AtCoder Beginner Contest 267 E Erasing Vertices 2
    ErasingVertices2二分||贪心二分的做法就二分答案,然后检查一下能否删除,像拓扑一下跑一下就行#include<iostream>#include<cstdio>#include<algorithm>#includ......
  • 1475. 商品折扣后的最终价格
    1475.商品折扣后的最终价格给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到......
  • AtCoder ABC 259 F Select Edges
    题意:​ 给出一棵树,边带权,对于点i,最多保留d[i]条边,可以被分成连通块,请问边权和最大是多少分析:​ 因为可以被分成连通块,我们就可以对点i划分两种状态。第一种是点i不与父......
  • AtCoder Beginner Contest 266 G,H
    G考虑先放G和B,此时共有\(C_{G+B}^{B}\)种方案。然后选出\(k\)个G,在前面放上\(R\),共有\(C_{G}^{k}\)种方案。最后我们放剩下的\(R-K\)个R,考虑目前哪些区间内部可以放一段......
  • 1470. 重新排列数组
    1470.重新排列数组给你一个数组nums,数组中有2n个元素,按[x1,x2,...,xn,y1,y2,...,yn]的格式排列。请你将数组按[x1,y1,x2,y2,...,xn,yn]格式重新排列,返回重排......
  • P1471 方差
    给定数列,维护区间平均数和区间方差,并支持区间修改。\(n\leq10^5,m\leq10^5\)。线段树维护平均数比较简单,重点在于如何维护方差。具体公式参考了这篇题解,就不详细展开,推......
  • AtCoder Beginner Contest 266 一句话题解
    AandBsbt,不讲。C垃圾计算几何,问是不是一个凸包,搞份板子交就可以了。D简单dp,令\(f(i,j)\)表示第\(i\)个时间在第\(j\)个位置的最大价值,从上一个时间转移,可以......
  • AtCoder Beginner Contest 266
    比赛链接:https://atcoder.jp/contests/abc266C-ConvexQuadrilateral题意:平面图上有一个四边形,按照逆时针顺序给定四个点的坐标,判断四边形是不是凸的。思路:求两条......