1. 程式人生 > 其它 >AcWing周賽43

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. 題目直接給的 :\(1 \leqslant b_i \leqslant a_i\)

  2. 通過 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;

}