首页 > 其他分享 >ABC221 复盘

ABC221 复盘

时间:2024-04-04 10:44:39浏览次数:24  
标签:10 int ll sum 复杂度 ans ABC221 复盘

ABC221 复盘

[ABC221A] Seismic magnitude scales

思路解析

数据范围 \(B \le A \le 10\),可以发现能直接暴力求解。注意开 long long

code

//ABC221A
#include<bits/stdc++.h>
using namespace std;
int a, b;
int main() {
	cin >> a >> b;
	a -= b;
	long long ans = 1;
	for(int i = 1; i <= a; i++) {
		ans *= 32;
	}
	cout << ans;
	return 0;
}

[ABC221B] typo

思路解析

直接按照题意遍历 \(s\) 的每个下标与下一个下标交换,然后判断是否相同即可。注意可以不进行任何操作,要多一次判断。

时间复杂度:需要遍历每个下标\(O(\left\vert S \right\vert)\),而每次交换后的判断也需要 \(O(\left\vert S \right\vert)\),因此总复杂度为 \(O(\left\vert S \right\vert ^2)\)。

code

//ABC221B
#include<bits/stdc++.h>
using namespace std;
string s, t;
int main() {
	cin >> s >> t;
	if(s == t) {
		cout << "Yes";
		return 0;
	}
	for(int i = 1; i < s.size(); i++) {
		swap(s[i], s[i - 1]);
		if(s == t) {
			cout << "Yes";
			return 0;
		}
		swap(s[i], s[i - 1]);
	}
	cout << "No";
	return 0;
}

[ABC221C] Select Mul

思路解析

可以想到想让乘积最大尽量让位数更平均,而同时我们也需要让更大的位数排在更前面,于是我们可以先将原数存成数组从大到小排个序,然后贪心取即可。

时间复杂度:设 \(x=\log_{10}N+1\),有一层排序,因此复杂度为 \(O(x \log x)\)。

code

//ABC221C
#include<bits/stdc++.h>
using namespace std;
int n;
int main() {
	cin >> n;
	vector<int> v;
	while(n > 0) {
		v.push_back(n % 10);
		n /= 10;
	}
	sort(v.begin(), v.end(), [](int x, int y) {
		return x > y;
	});
	int x = 0, y = 0;
	for(int i = 0; i < v.size(); i++) {
		if(x <= y) x = x * 10 + v[i];
		else y = y * 10 + v[i];
	}
	cout << x * y;
	return 0;
}

[ABC221D] Online games

思路解析

首先可以想到先用差分打标记,最后结束时在统计即可。但可惜数据范围 \(A_i \le 10^9\),不能存下来每一个时间点,于是想到离散化。将每个区间离散成 \(2\) 个点存下来,这样总点数就只有 \(2 \times N\) 个,可以通过。最后拿区间之间的人数乘上区间长度即可。

时间复杂度:一次排序加去重,复杂度为 \(O(N \log N)\)。

code

//ABC221D
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, a[N], b[N], c[5 * N], ans[N];
int main() {
	cin >> n;
	vector<int> v;
	for(int i = 1; i <= n; i++) {
		cin >> a[i] >> b[i];
		v.push_back(a[i]);
		v.push_back(a[i] + b[i]);
	}
	v.push_back(n + 1);
	sort(v.begin(), v.end());
	v.erase(unique(v.begin(), v.end()), v.end());
	for(int i = 1; i <= n; i++) {
		int pa = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
		int pb = lower_bound(v.begin(), v.end(), a[i] + b[i]) - v.begin() + 1;
		c[pa]++; c[pb]--;
	}
	for(int i = 1; i < v.size(); i++) {
		c[i] += c[i - 1];
		ans[c[i]] += v[i] - v[i - 1];
	}
	for(int i = 1; i <= n; i++) {
		cout << ans[i] << ' ';
	}
	return 0;
}

[ABC221E] LEQ

思路解析

很有思维量的一道题。首先根据题目要求发现,新求的子序列只跟子序列的头尾有关,而在确定头尾之后中间的元素选或不选没有任何关系。也就是确定新子序列的头尾下标分别为 \(i,j\),那么以当前头尾的可行子序列个数就是 \(2^{j-i-1}=2^j \div 2^{i+1}\) 种可能。

接下来我们思考,根据题目要求,上方的 \(i,j\) 一定有 \(a_i \le a_j\),于是我们要做的其实就是找固定 \(j\),有多少个 \(i\) 使得 \(i<j,a_i \le a_j\),也就是个二维偏序。但事实上不需要那么复杂,假设有 \(i_1,i_2,\dots,i_k\) 都满足题目的条件,那么以 \(j\) 结尾的子序列的个数就是 \(2^j \div 2^{i_1+1}+2^j \div 2^{i_2+1}+\dots+2^j \div 2^{i_k+1}=2^j \div (2^{i_1+1}+2^{i_2+1}+\dots+2^{i_k+1})\)。

那么接下来就很轻松了,由于上方的 \(i,j\) 一定有 \(a_i \le a_j\),所以我们可以用一个 \(rk_i\) 存下 \(a_i\) 的排名,设 \(v_{rk_i}=2^{i+1}\),然后求 \(\sum_{k=1}^{rk_j-1}v_k\),这样我们就可以求得满足 \(a_i \le a_j\) 的条件所有的 \(i\) 对答案的贡献,还要继续考虑 \(i<j\) 这个条件。我们其实可以不先处理出来 \(v\) 的值,而是在 \(j \to j+1\) 时处理 \(v_j\) 的值,这样就能保证所有 \(v\) 当中有值的 \(v_{rk_i}\) 都有 \(i<j\)。由于 \(v\) 需要满足单点修改和区间求和的操作,所以需要使用树状数组优化。

注意:由于有取模和乘方,所以需要使用逆元和快速幂求解。

时间复杂度:需要遍历每个下标,都需要一次区间查询和单点修改,复杂度为 \(O(n \log n)\)。

code

//ABC211E
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 3e5 + 10;
const ll mod = 998244353;
int n, m;
ll a[N], c[N], b[N];
map<ll, int> rk;

ll ksm(ll a, ll b, ll p) {
	ll ans = 1;
	while(b) {
		if(b & 1) {
			ans = ans * a % p;
		}
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
ll niyuan(ll a, ll p) {
	return ksm(a, p - 2, p);
}

void add(ll x, ll y) {
	for(; x <= n; x += (x & -x)) {
		c[x] = (c[x] + y) % mod;
	}
}
ll ask(ll x) {
	ll sum = 0;
	for(; x > 0; x -= (x & -x)) {
		sum = (sum + c[x]) % mod;
	}
	return sum;
}

int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		b[i] = a[i];
	}
	sort(b + 1, b + n + 1);
	for(int i = 1; i <= n; i++) {
		rk[b[i]] = i;
	}
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		ans = (ans + (ksm(2, i, mod) * ask(rk[a[i]])) % mod) % mod;
		add(rk[a[i]], ksm(niyuan(2, mod), i + 1, mod));
	}
	cout << ans;
	return 0;
}

[ABC221G] Jumping sequence

思路解析

题意很好理解,四向移动,步长确定,可见移动方式非常复杂,\(x,y\) 轴分别有三种可能的偏移量,于是我们选择将整个坐标系顺时针旋转 \(45^\circ\),这样偏移量就只有加减两种可能,同时终点也变成了 \((x-y,x+y)\)。如此题目就变成了一道可行性背包问题,可以用 \(f_{i,j}\) 表示走了 \(i\) 步,第 \(j\) 行/列能否到达,由于每次行和列的偏移量的值相同,因此可以存在一个数组内。最后就是用 bitset 优化然后判断一下能否到达并根据 dp 过程中的值输出路径即可。

时间复杂度:\(O(N)\)。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 2010, M = 3.6e6 + 10;
int n, a, b, d[N], x, y, ans[N];
bitset<M> f[N];
int main() {
	cin >> n >> a >> b;
	x = a - b, y = a + b;
	int sum = 0;
	for(int i = 1; i <= n; i++) {
		cin >> d[i];
		sum += d[i];
	}
	if(sum < abs(x) || sum < abs(y)) {cout << "No"; return 0;}
	if((x + sum) % 2 == 1 || (y + sum) % 2 == 1) {cout << "No"; return 0;}
	x = (x + sum) / 2, y = (y + sum) / 2;
	f[0][0] = true;
	for(int i = 1; i <= n; i++) {
		f[i] = f[i - 1] | (f[i - 1] << d[i]);
	}
	if(!f[n][x] || !f[n][y]) {cout << "No"; return 0;}
	cout << "Yes\n";
	for(int i = n; i >= 1; i--) {
		if(f[i - 1][x] && f[i - 1][y]) ans[i] = 0;
		else if(!f[i - 1][x] && f[i - 1][y]) ans[i] = 1;
		else if(f[i - 1][x] && !f[i - 1][y]) ans[i] = 2;
		else if(!f[i - 1][x] && !f[i - 1][y]) ans[i] = 3;
		if(ans[i] & 1) x -= d[i];
		if(ans[i] & 2) y -= d[i];
	}
	for(int i = 1; i <= n; i++) {
		if(ans[i] == 0) cout << "L";
		else if(ans[i] == 1) cout << "D";
		else if(ans[i] == 2) cout << "U";
		else if(ans[i] == 3) cout << "R";
	}
	return 0;
}

标签:10,int,ll,sum,复杂度,ans,ABC221,复盘
From: https://www.cnblogs.com/2020luke/p/18113969

相关文章

  • [ABC221E] LEQ 题解
    [ABC221E]LEQ题解思路解析很有思维量的一道题。首先根据题目要求发现,新求的子序列只跟子序列的头尾有关,而在确定头尾之后中间的元素选或不选没有任何关系。也就是确定新子序列的头尾下标分别为\(i,j\),那么以当前头尾的可行子序列个数就是\(2^{j-i-1}=2^j\div2^{i+1}\)种......
  • Java后端新手的第一次面试复盘
    昨天经历了第一次Java后端实习生面试,在无数次的简历投递后,很难得的一次面试机会,收获很多,也深刻感受到自己能力的不足(还需要继续沉淀半个学期),在此记录下收获和感悟,如有错误,欢迎指正!1.面试流程闲聊(5分钟):自我介绍+询问背景动机技术问答(45分钟):包括Java基础、数据库技......
  • ABC221H Count Multiset
    传送门构造序列型DP。经典的就是这么一种构造序列的方式:用两种操作。增加一个\(0\)。将当前序列中所有数加\(1\)。由此可以构造出任意一种自然数不降序列。回到本题。即要求构造一个长度\(k\)和为\(n\)且没有一种数出现超过\(m\)次的不降序列,求方案数。考虑......
  • 转盘小程序首页运营复盘记录
    转盘小程序首页运营复盘记录~今天是4月1号,距离我的转盘小程序上线也一月有余了正如大家期待的那样,是的,我的转盘小程序已经在3月份正式上线发布了,具体的时间线如下所示  *2024-03-30功能完善,增加敏感词过滤*2024-03-25功能完善,支持语音播报*2024-03-20功能完善,新增......
  • Kaggle量化比赛复盘: Optiver - Trading at the Close
    目录前言一、开源方案1.6th获奖方案(代码未开源)1.1.特征工程(关键代码)1.2.方案解析2. 7th获奖方案(开源)2.1.特征工程2.2.特征工程3. 9th获奖方案(半开源)3.1.特征构造3.2.特征筛选3.3.模型3.4.zero_sum(标签后处理)4. 14th获奖方案(开源)4.1.方案......
  • BUPT 2024 Spring Training #3(ICPC2023 杭州站)Ag复盘
    D-OperatorPrecedence求一个长度为\(2n\)的序列\(a_{2n}\)满足条件\((a_1×a_2)+(a_3×a_4)+\ldots+(a_{2n-1}×a_{2n})=a_1×(a_2+a_3)×\ldots×(a_{2n-2}+a_{2n-1})×a_{2n}\)solution构造题显然找特殊规律。考虑到乘法构造难度大于加法,可以从乘法开始考虑。......
  • 贪心刷题复盘
    最近练了一些贪心的题目,虽然思想都是局部最优的思想,但是落实到每一题上其实会有细微的差别,复盘一下题目加深印象。P2240【深基12.例1】部分背包问题这一题按照性价比排序就可以了,性价比最高的排在最前面。为了避免除法带来的问题,我们比较两个点的性价比用叉乘的方式来比较点......
  • 「ABC221D」 Online games
    题意给\(n\)组整数\(a_i\)和\(b_i\),表示有一个人在\([a_i,a_i+b_i)\)登录。求\(\forallk\in[1,n]\),有\(k\)个玩家登录的天数。分析很明显的差分,但是因为\(a_i,b_i\le10^9\),不能直接开差分数组。注意到\(n\le2\times10^5\),所以可以用pair数组代替差分数组,......
  • 代码复盘bug
    代码有bug执行10000次最后只赛进去1个Process因为CloudServicecloudService=(CloudService)vertexModel;这里的cloudService变量会被共享,重复不断被覆盖vertexModelList.add(cloudService);publicvoidtestAddVertex(intcount,VertexModelvertexModel){......
  • 牛客小白月赛88 出题复盘
    回顾初次投题是在2023.10.27,由于不熟悉流程,是自己拉了个内测确保题目都完整了才投的(题面+数据+题解全搞定了),后来发现投题的时候其实只需要一个idea加上一个题解。随后恰好赶上年末赛季(猜测,因为确实过了很久),一直拖到2023.12.26才正式进行录题。中途换了一次审题人,到2024.01.1......