Educational Codeforces Round 23
https://codeforces.com/contest/817
数据结构专场。
A. Treasure Hunt
#include <bits/stdc++.h>
using namespace std;
int main () {
int x1, x2, y1, y2, x, y;
cin >> x1 >> y1 >> x2 >> y2 >> x >> y;
int dx = abs(x2 - x1), dy = abs(y2 - y1);
if ((dx % x) || (dy % y)) {
cout << "NO";
return 0;
}
int cntx = dx / x, cnty = dy / y;
//cout << cntx << ' ' << cnty << endl;
if ((cntx % 2) != (cnty % 2)) cout << "NO";
else cout << "YES";
}
B. Makes And The Product
分类讨论没想清楚。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
int a[N], n;
int main () {
cin >> n;
map<int, int> mp;
for (int i = 1; i <= n; i++) cin >> a[i], mp[a[i]] ++;
sort (a + 1, a + n + 1);
ll ans = 0;
if (a[3] == a[1]) ans = (1ll * mp[a[1]] * (mp[a[1]] - 1) * (mp[a[1]] - 2)) / 6;
else if (a[2] == a[3]) ans = (1ll * mp[a[2]] * (mp[a[2]] - 1)) / 2;
else ans = mp[a[3]];
cout << ans << endl;
}
//第三小的数字有多少个
C. Really Big Numbers
打表发现单调性之后直接二分。
此题因为过于重视研究规律而没有往算法的方向想emmm很可惜
// LUOGU_RID: 102953585
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll cal (ll x) { //打表
string s = to_string (x);
ll sum = 0;
for (int i = 0; i < s.size (); i++) sum += (s[i] - '0');
return abs (x - sum);
}
int main () {
ll n, s;
cin >> n >> s;
// for (ll i = 0; i <= 10000; i += 10) {
// ll dx = cal (i);
// cout << i << ' ' << dx << endl;
// }
//根据s倒推数字
ll l = 0, r = n + 1;
while (l < r) {
ll mid = l + r >> 1;
if (cal (mid) < s) l = mid + 1;
else r = mid;
}
cout << max (0ll, n - r + 1) << endl;
}
//逢10进9, 逢100进18, 逢1000进27, ... ,
//打表出单调性之后直接二分
D. Imbalanced Array
四颗单调栈维护该值左右能覆盖到的范围,类似函数区域内的极值。
但是有很多小细节要注意,比如左右只有一边能取到等,这是为了防止重复选取111..这种一大片一样的。
// LUOGU_RID: 102977042
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
int a[N], n;
ll lMax[N], rMax[N], lMin[N], rMin[N]; //a[i]作为最值的作用范围
stack<int> stk;
int main () {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
//左Max
a[0] = 1e9;
stk.push (0);
for (int i = 1; i <= n; i++) {
if (a[i] < a[stk.top ()]) lMax[i] = i - 1, stk.push (i);
else {
while (stk.size () && a[i] >= a[stk.top ()]) stk.pop ();
lMax[i] = stk.top ();
stk.push (i);
}
}
//左Min
a[0] = 0;
while (!stk.empty ()) stk.pop ();
stk.push (0);
for (int i = 1; i <= n; i++) {
if (a[i] > a[stk.top ()]) lMin[i] = i - 1, stk.push (i);
else {
while (stk.size () && a[i] <= a[stk.top ()]) stk.pop ();
lMin[i] = stk.top ();
stk.push (i);
}
}
//右Max
a[n + 1] = 1e9;
while (!stk.empty ()) stk.pop ();
stk.push (n + 1);
for (int i = n; i >= 1; i--) {
if (a[i] < a[stk.top ()]) rMax[i] = i + 1, stk.push (i);
else {
while (stk.size () && a[i] > a[stk.top ()]) stk.pop ();
rMax[i] = stk.top ();
stk.push (i);
}
}
//右Min
a[n + 1] = 0;
while (!stk.empty ()) stk.pop ();
stk.push (n + 1);
for (int i = n; i >= 1; i--) {
if (a[i] > a[stk.top ()]) rMin[i] = i + 1, stk.push (i);
else {
while (stk.size () && a[i] < a[stk.top ()]) stk.pop ();
rMin[i] = stk.top ();
stk.push (i);
}
}
//for (int i = 1; i <= n; i++) cout << lMin[i] << ' ' << rMin[i] << ' ' << lMax[i] << ' ' << rMax[i] << endl;
ll ans = 0;
for (int i = 1; i <= n; i++) {
ans += 1ll * a[i] * (1ll * (rMax[i] - i) * (i - lMax[i]) - 1ll * (rMin[i] - i) * (i - lMin[i]));
}
cout << ans << endl;
}
//任意子区间的最大最小值之差
//四个单调栈分别维护
//注意细节: 右等左不等
E. Choosing The Commander
01Trie树
按位统计:
当前位为1:统计k=0上子树答案,向k=1子树遍历
当前位为0:遍历k=0子树
有一个不懂的就是为什么下标idx一定要从1开始
// LUOGU_RID: 102992350
#include <bits/stdc++.h>
using namespace std;
const int N = 3100005;
int son[N][2], cnt[N], idx = 1;//下标0的点,是根节点,也是空节点;存节点的子节点;cnt[]存储以每个节点结尾的单词数量
void insert(int x, int d) {
int p = 1;
for (int i = 31; i >= 0; i--) {
bool u = (x >> i) & 1;
if (!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
cnt[p] += d;
}
}
int query(int x, int y) {
int p = 1, sum = 0;
for (int i = 31; i >= 0; i--) {
bool u = (x >> i) & 1, v = (y >> i) & 1;
if (v == 1) sum += cnt[son[p][u]], p = son[p][u^1];
else p = son[p][u];
}
return sum;
}
int main () {
int n, op, x, y;
cin >> n;
while (n --) {
cin >> op;
if (op == 1) {
cin >> x;
insert (x, 1);
}
else if (op == 2) {
cin >> x;
insert (x, -1);
}
else {
cin >> x >> y;
cout << query (x, y) << endl;
}
}
}
//01-trie树
//当前位为1:统计k=0上子树答案,向k=1子树遍历
//当前位为0:遍历k=0子树
//为什么下标从1开始
F. MEX Queries
复杂线段数
标签:Educational,23,int,cin,ll,Codeforces,stk,else,top From: https://www.cnblogs.com/CTing/p/17155268.html