A.Lily
题意
思路
数所有周围没L的格子
#include <bits/stdc++.h>
using i64 = long long;
constexpr int N = 2e5 + 10;
constexpr int mod = 1e9 + 7;
constexpr int Inf = 0x3f3f3f3f;
constexpr double eps = 1e-10;
std::string s;
int n;
void solve() {
std::cin >> n >> s;
s = " " + s;
for (int i = 1; i <= n; i ++) {
if (s[i] == 'L') continue;
if (i == 1) {
if (s[i + 1] != 'L') {
s[i] = 'C';
}
}else if (i == n) {
if (s[i - 1] != 'L') {
s[i] = 'C';
}
}else {
if (s[i - 1] != 'L' && s[i + 1] != 'L') {
s[i] = 'C';
}
}
}
std::cout << s.substr(1, n) << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
while(t --) {
solve();
}
return 0;
}
M. Youth Finale
题意
给定一个排列,每次可以翻转这个排列,或者循环往左一个单位,给定操作序列,问操作之后给序列做冒泡排序的操作次数
思路
冒泡排序的操作次数其实就是逆序对的对数,那就是求操作之后的逆序对有多少
考虑DS的思想,我们对它的逆序对统计,考虑两次操作对逆序对的贡献
第一种就是逆序对个数 = 长度 - 逆序对个数
对于第二种,考虑操作一下,变化量就是 cur - pre
cur就是原序列中比操作数大的数
pre就是原序列中比操作数小的数
减一下就行
然后发现需要维护操作数,那就拿个 idx 维护即可,发现第一种操作会让方向反向,因此维护 x 方向
#include <bits/stdc++.h>
#define int long long
using i64 = long long;
#define lowbit(x) (x & (- x))
constexpr int N = 1e6 + 10;
constexpr int mod = 1e9 + 7;
constexpr int Inf = 0x3f3f3f3f;
constexpr double eps = 1e-10;
std::string s;
int n, m;
int p[N];
int tr[N];
void add(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += k;
}
int query(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
void solve() {
std::cin >> n >> m;
for (int i = 1; i <= n; i ++) std::cin >> p[i];
std::cin >> s;
s = " " + s;
int cur = 0;
for (int i = 1; i <= n; i ++) {
cur += query(n) - query(p[i]);
add(p[i], 1);
}
std::cout << cur << "\n";
int idx = 1, x = 1;
for (int i = 1; i <= m; i ++) {
if (s[i] == 'S') {
cur = cur - (p[idx] - 1) + (n - (p[idx] + 1) + 1);
idx = idx + x;
if (idx == n + 1) idx = 1;
else if (idx == 0) idx = n;
}else {
cur = n * (n - 1) / 2 - cur;
idx = idx - x;
if (idx == 0) idx = n;
else if (idx == n + 1) idx = 1;
x = -x;
}
std::cout << cur % 10;
}
std::cout << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
while(t --) {
solve();
}
return 0;
}
E. Draw a triangle
题意
思路
#include <bits/stdc++.h>
#define int long long
using i64 = long long;
#define lowbit(x) (x & (- x))
constexpr int N = 1e6 + 10;
constexpr int mod = 1e9 + 7;
constexpr int Inf = 0x3f3f3f3f;
constexpr double eps = 1e-10;
int a, b, c, d;
int v, u;
int exgcd(int a, int b, int &v, int &u) {
if (!b) {
v = 1, u = 0;
return a;
}
int gcd = exgcd(b, a % b, u, v);
u -= (a / b) * v;
return gcd;
}
void solve() {
std::cin >> a >> b >> c >> d;
int x = c - a;
int y = d - b;
int gcd = exgcd(x, -y, v, u);
std::cout << a + u << " " << b + v << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
std::cin >> t;
while(t --) {
solve();
}
return 0;
}
C. Array Concatenation
题意
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define int long long
typedef long long lld;
const int N = 100005;
const lld p = 1000000007;
lld sum[N], a[N], tot[N];
lld powe(lld a, lld b) {
lld base = 1;
while(b) {
if(b & 1) base = base * a % p;
a = a * a % p; b >>= 1;
}
return base;
}
lld pos_t = 0, neg_t = 0, squ = 0;
lld ans1 = 0, ans2 = 0;
signed main() {
int n, m; scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
squ += a[i]; squ %= p;
}
for(int i = 1; i <= n; i++) {
sum[i] = (sum[i - 1] + a[i]) % p;
pos_t = (pos_t + sum[i]) % p;
}
for(int i = n; i >= 1; i--) {
tot[i] = (tot[i + 1] + a[i]) % p;
neg_t = (neg_t + tot[i]) % p;
}
squ = squ * n % p;
ans1 = ans2 = squ * powe(2, m - 1) % p * (powe(2, m) - 1 + p) % p;
ans1 = (ans1 + powe(2, m - 1) * pos_t % p) % p;
ans1 = (ans1 + powe(2, m - 1) * neg_t % p) % p;
ans2 = (ans2 + powe(2, m) * pos_t % p) % p;
printf("%lld", max(ans1, ans2));
return 0;
}