AcWing周赛43
AcWing周赛43
题源:https://www.acwing.com/activity/content/1233/
4314. 三元组
直接暴力做就是了,我一开始还在找规律。。悲
我滴代码
#include <iostream>
#include <algorithm>
using namespace std;
int n, cnt;
int main (){
cin >> n;
for (int i = 1; i <= n; i ++)
for (int j = i; j <= n; j ++){
int k = i^j;
if (k >= j && k <= n && i + j > k && i + k > j)
cnt ++;
}
cout << cnt << endl;
}
4315. 两个数列
就是两个不等式联立,我还傻傻的找规律,笨死了qaq
思路
-
题目直接给的 :\(1 \leqslant b_i \leqslant a_i\)
-
通过 sum 表示 : $ s_b - s_a + a_i \leqslant b_i \leqslant s_b - n + 1$
核心过程:
(\(s_i 表示 除b_i外的其他b之和,s_a表示所有a之和,s_表示所有b之和\))
\[由定义得,b_i = s_b - s_i,即 s_i = s_b + b_i\\ \because n - 1 \leqslant s_i \leqslant s_a - a_i\\ \therefore s_b - s_a + a_i \leqslant b_i \leqslant s_b - n + 1 \]更详细的推导:
(
字丑请见谅orz毕竟是在电脑上写字)
然后 b_i 的范围就是1. 2. 不等式取交集
我滴代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
ll n, sb, sa;
ll a[N];
int main (){
cin >> n >> sb;
for (int i = 1; i <= n; i ++)
cin >> a[i], sa += a[i];
if (n == 1)
cout << a[1] - 1 << endl;
else{
for (int i = 1; i <= n; i ++){
ll l = max (1ll, sb - sa + a[i]), r = min (a[i], sb - n + 1);
//cout << l << ' ' << r << endl;
cout << a[i] - (r - l + 1) << ' ';
}
}
}
4316. 合适数对
思路
考的时候想到用线段树来做,但是我不会QAQ
y总:离散化 + 树状数组 + 二分
鉴于我想不出来,就参考着自己写一遍
代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 4e5 + 5;//记得开两倍
ll n, m, s[N], xs[N],tr[N], cnt;
int get (ll x){
ll l = 1, r = cnt;
while (l < r){
ll mid = l + r >> 1;
if (xs[mid] >= x)
r = mid;
else
l = mid + 1;
}
return r;
}//离散化之后就可二分
void add (int x, int y){
for (int i = x; i < N; i += i & (-i))
tr[i] += y;
}
int query (int x){
ll ans = 0;
for (int i = x; i ; i -= i & (-i))
ans += tr[i];
return ans;
}
//均为树状数组板子
int main (){
cin >> n >> m;
xs[++ cnt] = 0, xs[++ cnt] = -m;
for (int i = 1; i <= n; i ++){
int x; cin >> x;
s[i] = s[i - 1] + x;
xs[++ cnt] = s[i], xs[++ cnt] = s[i] - m;
}
sort (xs + 1, xs + cnt + 1);
cnt = unique (xs + 1, xs + cnt + 1) - xs - 1;
//离散化处理
ll ans = 0;
add (get(0), 1);//j - 1会取到 0 的状况
for (int i = 1; i <= n; i ++){
ans += i - query (get (s[i] - m));
add (get(s[i]), 1);
}
cout << ans << endl;
}