传送门
A Remove Duplicates
记录每个数最后出现的位置,最后按照顺序输出即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010;
int a[N];
int n;
vector<int> ans;
bool vis[N];
int b[N];
void solve() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = n - 1; i >= 0; i--) {
if (!b[a[i]]) {
ans.push_back(a[i]);
b[a[i]] = 1;
}
}
//reverse(ans.begin(),ans.end());
cout<<ans.size()<<endl;
for (int i = 0; i < n; i++) {
if (ans.back() == a[i] && !vis[a[i]]) {
cout << a[i] << ' ';
vis[a[i]] = true;
ans.pop_back();
}
}
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin >> h_h;
h_h = 1;
while (h_h--)solve();
return 0;
}
B File Name
把每一个连续x的字符串删除到只剩2个,注意循环结束后最后可能还会由以x字符串结尾,所以还要判断一次
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010;
int a[N];
bool vis[N];
int b[N];
void solve() {
int n;
cin >> n;
string s;
cin >> s;
int res = 0;
int ans = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'x') {
res++;
} else {
if (res > 2)ans += res - 2;
res = 0;
}
}
if (res > 2)ans += res - 2;
cout << ans << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin >> h_h;
h_h = 1;
while (h_h--)solve();
return 0;
}
C Letters
简单的前缀和和二分,二分都有点忘了,记得复习,也可以直接使用库函数lower_bound
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010;
int a[N];
bool vis[N];
int b[N];
int n, m;
int s[N], s1[N];
int check(int x) {
int l = 1, r = n;
while (l < r) {
int mid = l + r >> 1;
if (s[mid] >= x)r = mid;
else l = mid + 1;
}
return l;
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= m; i++)cin >> b[i];
for (int i = 1; i <= n; i++)s[i] = s[i - 1] + a[i];
for (int i = 1; i <= m; i++) {
int j = check(b[i]);
//cout<<j<<endl;
cout << j << ' ' << b[i] - s[j - 1] << endl;
j = 1;
}
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin >> h_h;
h_h = 1;
while (h_h--)solve();
return 0;
}
D Almost Arithmetic Progression
又是一题经典的思维题,反正无论什么情况,每个数的改变情况只有三种,而一个等差数列当首项和公差确定了就完全确定了,所以我们其实选任意两项来确定公差和首项就可以枚举所有的序列情况,但为了方便用前两项来确定数列即可,在注意判断是否符合题意,而任意两项有九种情况每一项都有+1,-1,0三种情况。
#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int N = 100010;
int n;
int a[N];
int b[N];
void solve() {
cin >> n;
int mi = INT_MAX;
for (int i = 1; i <= n; i++)cin >> a[i];
if (n <= 2) {
cout << 0 << endl;
return;
}
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
b[1] = a[1] + i;
b[2] = a[2] + j;
int d = b[2] - b[1];
bool ok = true;
int cnt = abs(i) + abs(j);
for (int k = 3; k <= n; k++) {
b[k] = b[k - 1] + d;
if (abs(b[k] - a[k]) > 1) {
ok = false;
break;
}
if (b[k] != a[k])cnt++;
}
if (!ok)continue;
mi = min(mi, cnt);
}
}
if (mi == INT_MAX)puts("-1");
else cout << mi << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin>>h_h;
h_h=1;
while(h_h--)solve();
return 0;
}
E Bus Video System
读懂题目就行,其实就是求一个前缀和,但这个前缀和必须包括车进第一个站之前的车上的人数,总数必须在0-w之间,起始人数最少是在前缀和中最小的,最多是在前缀和中最大的,但要注意最小的和零求min,最大的和w求max,不能超过边界,最后看看两者之间有多少个数就是所有情况。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 100010;
int n, m;
int a[N];
int b[N];
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i++)cin >> a[i], a[i] += a[i - 1];
int mx = *max_element(a + 1, a + n + 1);
int mn = *min_element(a + 1, a + n + 1);
mn = max(0ll, -mn);
mx = min(m - mx, m);
if (mn > mx)cout << 0 << endl;
else cout << mx - mn + 1 << endl;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin>>h_h;
h_h=1;
while(h_h--)solve();
return 0;
}
F Mentors
先用二分求比这个数小的有多少个,然后再枚举争吵的两个人,让大的那个人减一,因为两个人争吵对小的那个人没有影响,最后输出答案即可。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 200010;
int n, m;
int a[N];
int b[N];
int cnt[N];
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i++)cin >> a[i], b[i] = a[i];
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
int l = 0, r = n + 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] < b[i])l = mid + 1;
else r = mid;
}
// cout << r << ' ' << a[r] << endl;
cnt[i] = l - 1;
}
//for (int i = 1; i <= n; i++)cout << cnt[i] << ' ';
while (m--) {
int x, y;
cin >> x >> y;
if (b[x] > b[y]) cnt[x]--;
if (b[x] < b[y]) cnt[y]--;
}
for (int i = 1; i <= n; i++)cnt[i] = max(0ll, cnt[i]), cout << cnt[i] << ' ';
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin>>h_h;
h_h = 1;
while (h_h--)solve();
return 0;
}
G Petya's Exams
最关键的一点就是要按照考试的时间排序,因为要优先复习先考试的科目,最后根据题目条件模拟一下即可。
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N = 110;
int n, m;
int ans[N];
struct S {
int a, b, c, cnt, id;
bool operator<(const S &t) const {
return b < t.b;
}
}a[N];
void solve() {
cin >> n >> m;
for (int i = 1; i <= m; i++)cin >> a[i].a >> a[i].b >> a[i].c, ans[a[i].b] = m + 1, a[i].id = i;
sort(a + 1, a + m + 1);
for (int i = 1; i <= m; i++) {
// for (int j = a[i].a; j <= a[i].a + a[i].c - 1; j++) {
// if (ans[j] != 0)continue;
// ans[j] = a[i].id;
// a[i].cnt++;
// }
for (int j = a[i].a; j < a[i].b; j++) {
if (ans[j] == 0 && a[i].cnt < a[i].c) {
a[i].cnt++;
ans[j] = a[i].id;
}
}
if (a[i].cnt < a[i].c) {
cout << -1 << endl;
return;
}
}
for (int i = 1; i <= n; i++)cout << ans[i] << ' ';
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int h_h;
//cin >> h_h;
h_h = 1;
while (h_h--)solve();
return 0;
}