[Atcoder] ARC133
A - Erase by Value

题意
给出一个序列A,选择一个数x,将这个序列里的x都移除,求操作完后字典序最小的序列
思路
找到第一次出现后一个数字小于前一个数字的位置,这样删除后必定是字典序最小的
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
int main(){
int n;
cin >> n;
int minn = 0;
bool fg = true;
int re = 0;
int num = re;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
if(i == 1) re = a[i];
else if(fg){
if(re == a[i]) continue;
else if(re < a[i]){
re = a[i];
}
else {
num = re;
fg = false;
}
}
}
if(num == 0) num = re;
for(int i = 1; i <= n; i ++) {
if(num == a[i]) continue;
else {
fg = false;
cout << a[i] << " ";
}
}
if(fg) cout << " ";
cout << endl;
return 0;
}
B - Dividing Subsequence

题意
给出1~N的排列P,Q。选择P和Q中相等长度的子序列,构成a = (a1, a2, ..., ak) 和 b = (b1, b2, ..., bk)。其中对于i = 1 ~ k,bi都是ai的倍数。求符合条件的子序列长度的最大值
思路
这题主要是二分查最长严格递增子序列
首先找出所有符合条件的数对,按pair存ai, bi的下标,在对first按升序排序,second按降序排序后,直接在second里用二分找最长严格上升子序列即可,因为first相同时second是降序的,所以找到的序列一定是符合条件的(这里不理解的话可以自己用案例推一下)
对于二分找最长严格上升子序列,如果当前元素比序列里最后一个元素大,就直接加到序列末尾。否则就二分在序列里找到第一个大于或等于这个数的位置,将其替换。
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 2e7 + 10;
PII pii[N];
int a[N], b[N];
vector<int> ans;
bool cmp(PII x, PII y) {
if(x.first == y.first) return x.second > y.second;
else return x.first < y.first;
}
int main(){
int n;
cin >> n;
int x;
for(int i = 1; i <= n; i ++) {
cin >> x;
a[x] = i;
}
for(int i = 1; i <= n; i ++) {
cin >> x;
b[x] = i;
}
int cnt = 0;
for(int i = 1; i <= n; i ++) {
for(int j = i; j <= n; j += i) {
pii[cnt ++] = {a[i], b[j]};
}
}
sort(pii, pii + cnt, cmp);
for(int i = 0; i < cnt; i ++) {
PII temp = pii[i];
if(ans.empty()) {
ans.push_back(temp.second);
}
else if(temp.second > ans.back() || ans.empty()) {
ans.push_back(temp.second);
}
else {
int idx = lower_bound(ans.begin(), ans.end(), temp.second) - ans.begin();
ans[idx] = temp.second;
}
}
cout << ans.size() << endl;
return 0;
}

浙公网安备 33010602011771号