AcWing周賽43
阿新 • • 發佈:2022-03-20
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;
}