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;

}
posted @ 2022-03-20 11:54  Sakana~  阅读(28)  评论(1编辑  收藏  举报