C
题意:构造三个串使得
思维题。python代码比汉语更容易懂。
a,b,c,n=map(int,input().split())
mn = min([a,b,c])
s1,s2,s3='','',''
for _ in range(mn):s1+='o';s2+='o';s3+='o'
a-=mn;b-=mn;c-=mn
for _ in range(a):s1+='a';s2+='a'
for _ in range(b):s3+='b';s2+='b'
for _ in range(c):s3+='c';s1+='c'
while len(s1)<n: s1+='x'
while len(s2)<n: s2+='y'
while len(s3)<n: s3+='z'
if len(s1)>n or len(s2)>n or len(s3)>n:print('NO')
else :print(s1,s2,s3,sep='\n') 更python的写法
a, b, c, n = map(int, input().split())
mn = min(a, b, c)
s1 = 'o' * mn; s2 = 'o' * mn; s3 = 'o' * mn
a -= mn; b -= mn; c -= mn
s1 += 'a' * a; s2 += 'a' * a
s2 += 'b' * b; s3 += 'b' * b
s1 += 'c' * c; s3 += 'c' * c
if len(s1) > n or len(s2) > n or len(s3) > n: print('NO')
else: print(s1 + 'x' * (n - len(s1)), s2 + 'y' * (n - len(s2)), s3 + 'z' * (n - len(s3)), sep='\n')
F
我的做法是:考虑 连通分量数量 + 环数量 的奇偶性
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
int ht[N];
int fa[N];
void init_set(int n) {
for (int i = 1; i <= n; ++i) fa[i] = i;
}
int Find(int x) {
if (x != fa[x]) fa[x] = Find(fa[x]); //路径压缩
return fa[x];
}
int res = 0;
void merge(int x, int y) {
x = Find(x); y = Find(y);
if (x == y) ++res;
else fa[y] = x;
}
int main() {
int n, m, u, v;
cin >> n >> m;
init_set(n);
rep(i, 1, m) {
cin >> u >> v;
merge(u, v);
}
rep(i, 1, n) if (Find(i) == i)++ res;
puts(res & 1 ? "Alice" : "Bob");
return 0;
} I
可以对序列中的一些数+1,求所能获得的最小逆序对
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 2e5 + 7;
const int mod = 1e9 + 7;
#define lowbit(x) ((x) & (-x))
ll tree[N];
inline void add(int i, ll x) {
for (int pos = i; pos < N; pos += lowbit(pos)) tree[pos] += x;
}
inline ll query(int n) {
ll ans = 0;
for (int pos = n; pos; pos -= lowbit(pos)) ans += tree[pos];
return ans;
}
inline ll query(int l, int r) { return query(r) - query(l - 1); }
ll a[N], n;
bool vis[N];
signed main() {
sc(n);
rep(i, 1, n) sc(a[i]);
ll ans = 0;
add(a[1], 1);
rep(i, 2, n) {
ans += query(a[i] + 1, n);
add(a[i], 1);
}
for (int i = n; i; --i) {
if (vis[a[i] - 1]) --ans; // 这说明a[i], a[i]-1 这一逆序对存在 那么可以通过对后方的数+1来消除这个逆序对
else vis[a[i]] = 1;
}
pr(ans);
return 0;
} J
原题。浮点二分。
约分后可转化为a的最大均值 + b的最大均值 (长度大于等于k) 即为所求
的做法就是二分答案然后每次用前缀和做一个滑窗来处理。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m, x, y;
double maxAverage(vector<int> &nums, int k) {
double L = INT_MAX, R = INT_MIN;
for (int x : nums) {
if (x <= L) L = x;
if (x >= R) R = x;
}
int len = nums.size();
double sum[len + 1];
memset(sum, 0, sizeof(sum));
while (R - L > 1e-8) {
double mid = (L + R) / 2;
double min_pre = 0;
bool flag = false;
for (int i = 1; i <= len; i++) {
sum[i] = sum[i - 1] + nums[i - 1] - mid;
if (i >= k && sum[i] - min_pre >= 0) {
flag = true;
break; //只要有一组满足平均值大于mid就可以跳出内循环
}
if (i >= k) min_pre = min(min_pre, sum[i - k + 1]);
}
flag ? L = mid : R = mid;
}
return L;
}
signed main() {
scanf("%d%d%d%d", &n, &m, &x, &y);
vector<int> a(n), b(m);
for (int &x : a) scanf("%d", &x);
for (int &x : b) scanf("%d", &x);
printf("%.10f\n", maxAverage(a, x) + maxAverage(b, y));
return 0;
} 
京公网安备 11010502036488号