Codeforces Round #624 (Div. 3)
Codeforces Round #624 (Div. 3)
昨天vp的
https://codeforces.com/contest/1311
A. Add Odd or Subtract Even
以为成另一道题了。。。这里每次加减的数是可变的,所以:
#include <bits/stdc++.h>
using namespace std;
void solve () {
int a, b, ans;
cin >> a >> b;
if (a == b) ans = 0;
else if (a < b) {
int d = b - a;
if (d & 1) ans = 1;
else ans = 2;
}
else {
int d = a - b;
if (d & 1) ans = 2;
else ans = 1;
}
cout << ans << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//每次增减的数可变
B. WeirdSort
模拟完全冒泡排序,判断下标是否可以交换
优化:连续段一起交换
优化Code
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N], n, m, x;
void solve () {
cin >> n >> m;
set <int> s;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < m; i ++) cin >> x, s.insert (x);
for (int i = 1, j = 0; i <= n; i ++) {
if (s.count (i)) continue;
sort (a + j, a + i);
j = i;
}
if (is_sorted (a, a + n)) cout << "YES\n";
else cout << "NO\n";
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//冒泡
//当一段连续的pi存在时,就可以直接对这一段a[pi+i~pi+j]进行排序
//区间排序
C. Perform the Combo
有过少个比它大与等于的对应位置就加几
这里使用的是二分查找
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, ans[27];
void solve () {
string s;
cin >> n >> m >> s;
vector <int> v;
//vector <int> cnt(n+1, 0);
for (int i = 0; i < m; i ++) {
int x;
cin >> x;
v.push_back (x);
}
v.push_back (n);
sort (v.begin (), v.end());
memset (ans, 0, sizeof ans);
//有过少个比它大与等于的就加几
for (int i = 0; i < n; i ++) {
int x = lower_bound (v.begin(), v.end(), i+1) - v.begin();
x = m - x + 1;
ans[s[i] - 'a'] += x;
}
for (int i = 0; i < 26; i ++) cout << ans[i] << ' ';
cout << endl;
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//前缀和差分
//区间加
D. Three Integers
a的变化范围只能在[1,2a](超过2a不如变成1)
从而b在[a, 2b],
从而确定c的范围[b(c/b), b(c/b) + b]
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf = 0x7ffffffffffffff;
void solve () {
int a, b, c;
cin >> a >> b >> c;
int ans = inf, A, B, C;
for (int i = 1; i <= 2 * a; i ++)
for (int j = i; j <= 2 * b; j += i)
for (int k = 0; k <= 1; k ++) {
int l = j * (c / j) + k * j; //取整
int t = abs (i - a) + abs(j - b) + abs (c - l);
if (t < ans) {
ans = t, A = i, B = j, C = l;
}
}
cout << ans << endl << A << ' ' << B << ' ' << C << endl;
}
signed main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//每次可以+1或-1,使得 b%a==0 && c%b == 0
//a的变化范围只能在[1,2a]
E. Construct the Binary Tree
先放上分析,明天来补code
//n个节点的二叉树,深度之和为d
//根节点算第1层,num[1]=1
//深度计算:num[i]*(i-1),i表示层数且(0<=num[i]<=num[i-1]*2)
//层数d: [log2n+1, n]
//num[1]+2*num[2]+3*num[3]+...+(n-1)*num[n-1]=d
//
F. Moving Points
分析:
对于任意xj < xi(坐标):
若 vj > vi,则一定会追上,即dis(i,j)=0;
若 vj <= vi,则追不上,即dis(i,j)=xi-xj;
BIT 求和
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int n;
vector <int> a; //点的速度
int v[N], x[N]; //vj<=vi的j的个数 \sum_xj
pii p[N]; //坐标 速度
int lowbit (int x) {
return x & (-x);
}
void add (int *b, int x, int v) {
for (int i = x; i <= n; i += lowbit (i))
b[i] += v;
}
int query (int *b, int x) {
int ans = 0;
for (int i = x; i; i -= lowbit (i))
ans += b[i];
return ans;
}
signed main () {
cin >> n;
for (int i = 0; i < n; i ++) cin >> p[i].first;
for (int i = 0; i < n; i ++) cin >> p[i].second, a.push_back (p[i].second);
sort (p, p + n);
sort (a.begin(), a.end());
a.erase ((a.begin(), a.end()), a.end());
int ans = 0;
for (int i = 0; i < n; i ++) {
int pos = upper_bound (a.begin(), a.end(), p[i].second) - a.begin(); //找到第一个>的
ans += query(v, pos) * p[i].first - query (x, pos);
add (v, pos, 1), add (x, pos, p[i].first);
}
cout << ans << endl;
}