Codeforces Round #690 (Div. 3)
A题 Favorite Sequence
题意
有一个长度为\(n\)的数组\(a\),将\(a\)按照\(1,n,2,n-1,\dots\)的数序摆放得到数组\(b\),现在给你数组\(b\),求数组\(a\)。
思路
双指针扫一遍即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n;
int a[maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
int l = 1, r = n;
while(l <= r) {
printf("%d ", a[l]);
if(l == r) break;
printf("%d ", a[r]);
++l, -- r;
}
printf("\n");
}
return 0;
}
B题 Last Year's Substring
题意
给你一个由数字构成的字符串,问能否在最多删除一个子串的情况下使得字符串只剩下“2020”。
思路
因为最多删除一个子串,那么很容易发现“2020”一定是由原字符串的前几个字符和最后几个字符构成,枚举前后各取几个字符即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n;
int a[maxn];
int b[] = {2, 0, 2, 0};
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%1d", &a[i]);
}
if(n < 4) {
printf("NO\n");
continue;
}
bool can = false;
for(int i = 0; i <= 4; ++i) {
bool flag = true;
for(int j = 1; j <= i; ++j) {
if(a[j] != b[j-1]) {
flag = false;
}
}
for(int j = n; j > n - 4 + i; --j) {
if(a[j] != b[3-n+j]) {
flag = false;
}
}
if(flag) {
can = true;
break;
}
}
printf("%s\n", can ? "YES" : "NO");
}
return 0;
}
C题 Unique Number
题意
给你一个\(x\),问\(x\)是否可以是一个各位数互不相等的数的数位和,如果是请输出最小的解。
思路
我们可以发现大于45的一定是无解情况,对于有解的情况,要想解最小,那么低位肯定是越大越好,因此从低位开始依次放\(9,8,\dots\)即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, x;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &x);
if(x > 45) {
printf("-1\n");
continue;
}
int up = 9, ans = 0, pw = 1;
while(x) {
if(x < up) {
ans += x * pw;
break;
}
ans += up * pw;
pw *= 10;
x -= up;
--up;
}
printf("%d\n", ans);
}
return 0;
}
D题 Add to Neighbour and Remove
题意
给你一个长度为\(n\)的数组\(a\),你每次可以将某个位置上的数加到它旁边的数上(加完之后将当前位置的数从数组中移除),问最少需要操作多少次使得数组剩下的数全部相等。
思路
我们可以通过枚举最后剩下的数的值是多少来求解,由于第一个位置上的数只能与它右边的数进行合并,因此我们只需枚举第一堆是由哪些位置构成即可。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 3000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n;
int a[maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
int ans = n - 1;
for(int i = 1; i <= n; ++i) {
int sum = 0, tmp = 0, cnt = 1;
for(int j = 1; j <= i; ++j) sum += a[j];
for(int j = i + 1; j <= n; ++j) {
tmp += a[j];
if(tmp > sum) break;
if(tmp == sum) {
tmp = 0;
++cnt;
}
}
if(tmp == 0) {
ans = min(ans, n - cnt);
}
}
printf("%d\n", ans);
}
return 0;
}
E题 Close Tuples (hard version)
题意
给你一个长度为\(n\)的数组,求有多少个满足条件的m元组,条件:对于某个\(m\)元组,该\(m\)元组内的最大值减最小值不大于\(k\)。
思路
首先将数组排序,依次枚举最小值\(x\),二分计算在它后面有多少个数小于等于\(x+k\),假设为\(num\)个,那么对于这个最小值的贡献为\(C_{num}^{m-1}\)。
\(easy\)版本与\(hard\)版本的区别在于\(easy\)版本固定\(m=3,k=2\),且不需要取模。
代码
//easy
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n, m, k;
int a[maxn];
LL Combine(int n, int m) {
return 1LL * n * (n - 1) / 2;
}
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
k = 2, m = 3;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
LL ans = 0;
for(int i = 1; i <= n; ++i) {
int num = upper_bound(a + 1, a + n + 1, a[i] + k) - a - i - 1;
ans = ans + Combine(num, m - 1);
}
printf("%lld\n", ans);
}
return 0;
}
//hard
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n, m, k;
int a[maxn], A[maxn], inv[maxn];
int qpow(int x, int n) {
int ans = 1;
while(n) {
if(n&1) ans = 1LL * ans * x % mod;
x = 1LL * x * x % mod;
n >>= 1;
}
return ans;
}
void init() {
A[0] = 1;
for(int i = 1; i < maxn; ++i) A[i] = 1LL * A[i-1] * i % mod;
inv[maxn-1] = qpow(A[maxn-1], mod - 2);
for(int i = maxn - 2; i >= 0; --i) inv[i] = 1LL * inv[i+1] * (i + 1) % mod;
}
int Combine(int n, int m) {
if(n < m) return 0;
if(n == 0 || m == 0) return 1;
return 1LL * A[n] * inv[m] % mod * inv[n-m] % mod;
}
int main() {
init();
scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
LL ans = 0;
for(int i = 1; i <= n; ++i) {
int num = upper_bound(a + 1, a + n + 1, a[i] + k) - a - i - 1;
ans = (ans + Combine(num, m - 1)) % mod;
}
printf("%lld\n", ans);
}
return 0;
}
F题 The Treasure of The Segments
题意
给你\(n\)个区间,问最少删除多个条区间才能使得剩余的区间中有一个区间与其他剩余的区间有交点。
思路
我们枚举区间,计算它与多少个区间相交,设为\(num\),那么要删除的区间条数就是\(n-num-1\),这个写法需要借助线段数或树状数组。
我们逆向考虑计算有多少个区间与当前枚举的区间不相交,那么这些不相交的区间要么左端点大于当前区间的右端点,要么右端点小于当前区间的左端点,这个写法只需要使用二分就行。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define fi first
#define se second
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("../in","r",stdin)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int t, n;
pii seg[maxn];
int l[maxn], r[maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &seg[i].fi, &seg[i].se);
l[i] = seg[i].fi;
r[i] = seg[i].se;
}
sort(l + 1, l + n + 1);
sort(r + 1, r + n + 1);
int ans = n - 1;
for(int i = 1; i <= n; ++i) {
int cnt = lower_bound(r + 1, r + n + 1, seg[i].fi) - r - 1;
cnt += n - (upper_bound(l + 1, l + n + 1, seg[i].se) - l - 1);
ans = min(ans, cnt);
}
printf("%d\n", ans);
}
return 0;
}