Educational Codeforces Round 102 (Rated for Div. 2)
文章目录
前言
我是傻逼
A.Replacing Elements
先判一下a中最大元素是否<=d 如果否 再判一下最小的两个元素之和是否<=d就行了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 107;
int n, m, q, k, t, d, a[maxn], flag;
int main() {
cin >> t;
while (t--) {
flag = 0;
cin >> n >> d;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] > d) flag = 1;
}
if (flag == 0) {
puts("YES");
continue;
}
sort(a + 1, a + n + 1);
if (a[1] + a[2] <= d) puts("YES");
else puts("NO");
}
}
B.String LCM
我是傻逼 暴力调一个半小时
直接求出字符串的循环节 如果两个字符串循环节不一样无解
然后输出长度为lcm(n,m) 循环节相同的字符串就行了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 27;
int n, m, q, k, flag, sa, ta, sb, tb;
string s, t;
int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
int main() {
cin >> q;
while (q--) {
flag = sa = sb = ta = tb = 0;
cin >> s >> t;
//特判单字母的情况
n = s.length(); m = t.length();
if (n < m) {
swap(s, t);
swap(n, m);
}
for (int l = 1; l <= m; l++) {
if (n % l || m % l) continue;
int i = 0;
for (i = 0; i < n; i++) {
if (s[i] != s[i % l]) break;
}
if (i == n) {
for (int j = 0; j < m; j++) {
if (s[j] != t[j]) {flag = 0; goto gg;};
}
for (int k = 0; k < n*m/gcd(n, m); k++) {
putchar(s[k%l]);
}
putchar('\n');
flag = 1;
break;
}
if (flag == 1) break;
}
gg:
if (!flag) puts("-1");
}
return 0;
}
C.No More Inversions
可以暴力出小范围的数据来找找规律 比手玩高效(废话
a是固定的 为1 2 3 … k-(n-k) … k-1 k k-1 k-2 … k-(n-k)
逆序对一共有
(
n
−
k
)
2
=
1
+
3
+
5
+
7
+
.
.
.
+
(
n
−
k
)
(n-k)^2 = 1 + 3 + 5 + 7 + ... + (n-k)
(n−k)2=1+3+5+7+...+(n−k)个 全是下标k-(n-k)之后的数贡献的
那么b就是
p
[
1
]
p
[
2
]
p
[
3
]
.
.
.
.
p
[
k
−
(
n
−
k
)
]
.
.
.
p
[
k
−
1
]
p
[
k
]
p
[
k
−
1
]
.
.
.
.
p
[
k
−
(
n
−
k
)
]
p[1] p[2] p[3] .... p[k-(n-k)] ... p[k-1] p[k] p[k-1] .... p[k-(n-k)]
p[1]p[2]p[3]....p[k−(n−k)]...p[k−1]p[k]p[k−1]....p[k−(n−k)]
从下标为k-(n-k)的位置开始到b数组结束 这一段是对称的
对于形如 s 1 , s 2 , . . . , s k − 1 , s k , s k − 1 , . . . , s 1 s_1,s_2,...,s_{k-1},s_{k},s_{k-1},...,s_{1} s1,s2,...,sk−1,sk,sk−1,...,s1的序列 如果 s i s_i si互不相同 那么s的逆序对数固定,均为 ( k − 1 ) 2 (k-1)^2 (k−1)2
把
s
i
s_i
si按权值分组,每次取出任意两组,假设他们的值分别是x和y,形成的序列一定都是
.
.
.
x
.
.
.
y
.
.
.
x
.
.
.
...x...y...x...
...x...y...x...或者是
x
.
.
.
y
.
.
.
y
.
.
.
x
.
.
x...y...y...x..
x...y...y...x..结构的,这两种结构分别贡献一个和两个逆序对
所以一共有
C
k
−
1
2
+
k
−
1
=
(
k
−
1
)
2
C_{k-1}^2+k-1=(k-1)^2
Ck−12+k−1=(k−1)2对逆序对
所以b中的逆序对也全部来自对称的那一段
所以b前面只能顺序放1 2 3… k-(n-k)-1.
后面要字典序最大 只能把k放最前面了
所以p[k-(n-k)] == k,其之后的p递减
p前面从1开始递增
#include<bits/stdc++.h>
using namespace std;
int t, n, k;
int main() {
cin >> t;
while (t--) {
cin >> n >> k;
for (int i = 1; i < (2*k-n); i++) printf("%d ", i);
for (int i = k; i >= 2*k-n; i--) printf("%d ", i);
printf("\n");
}
}
D.Program
n个操作,m次询问
每次操作把x加一或者减一,求如果去掉第[l,r]次操作,剩下的操作过程中x会变成多少个不同的数
n,m<=2e5
注意到x的取值是连续的 所以求出区间最大值和最小值减一下就是答案
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 7;
#define ls p << 1
#define rs p << 1 | 1
struct _ {
int l, r, ans;
}e[maxn];
int t, n, m, a[maxn], mx[maxn << 2], mi[maxn << 2];
void build(int p, int l, int r) {
if (l == r) {mx[p] = mi[p] = a[l]; return;}
int mid = l + r >> 1;
build(ls, l, mid); build(rs, mid + 1, r);
mx[p] = max(mx[ls], mx[rs]);
mi[p] = min(mi[ls], mi[rs]);
}
int querymx(int p, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return mx[p];
}
int mid = l + r >> 1, res = -999999;
if (x <= mid) res = max(res, querymx(ls, l, mid, x, y));
if (y > mid) res = max(res, querymx(rs, mid + 1, r, x, y));
return res;
}
int querymi(int p, int l, int r, int x, int y) {
if (x <= l && r <= y) return mi[p];
int mid = l + r >> 1, res = 999999;
if (x <= mid) res = min(res, querymi(ls, l, mid, x, y));
if (y > mid) res = min(res, querymi(rs, mid+1, r, x, y));
return res;
}
int rd() {
int x;
scanf("%d", &x);
return x;
}
char s[maxn];
int main() {
t = rd();
while (t--) {
n = rd(), m = rd();
scanf("%s", s + 1);
int x = 0;
for (int i = 1; i <= n; i++) {
if (s[i] == '+') x++;
else x--;
a[i] = x;
}
build(1, 1, n);
for (int i = 1; i <= m; i++) {
e[i].l = rd(); e[i].r = rd();
int Mx = 0, Mi = 0, M1, M2, M3, m1, m2, m3;
if (e[i].l > 1) {
M1 = querymx(1, 1, n, 1, e[i].l - 1);
m1 = querymi(1, 1, n, 1, e[i].l - 1);
} else M1 = -999999, m1 = 999999;
if (e[i].r < n) {
M2 = querymx(1, 1, n, e[i].r+1, n) - a[e[i].r] + a[e[i].l - 1];
m2 = querymi(1, 1, n, e[i].r+1, n) - a[e[i].r] + a[e[i].l - 1];
} else M2 = -999999, m2 = 999999;
Mx = max(Mx, max(M1, M2));
Mi = min(Mi, min(m1, m2));
e[i].ans = Mx - Mi + 1;
//printf("Mx == %d Mi == %d\n", Mx, Mi);
}
for (int i = 1; i <= m; i++) {
printf("%d\n", e[i].ans);
}
}
}