Atcoder Beginner 119D 122C 題解(都是二分)

<At-119D>

題意:

給你一個n,一個m,表示有n個景點1,和m個景點2,q個查詢,表示你每次的位置。你想要至少遊覽景點1和景點2各一個,問你最小花費。

思路:

二分處理一下,分別處理當前查詢的位置的前後的景點1和景點2,然後

前1,前2; 前1,後2;

前2,前1;前2,後1;

後1,前2;後1,後2;

後2,前1;後2,後1。

8種方式維護一個最小值就ok了。

這裏提一下,upper_bound() 和 lower_bound() 使用的時候,一般都初始化第一項的前一項和最後一項的後一項(防止查不到下標的情況),具體值因題而定。

我的AC代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx = 1e5 + 7;
const int Inf = 1 << 30;
const ll INF = 1ll << 60;
int a, b, q;
ll s[maxx], t[maxx], dd;

int main() {
    scanf("%d %d %d", &a, &b, &q);
    for(int i = 1; i <= a; i++) scanf("%lld", &s[i]);
    for(int i = 1; i <= b; i++) scanf("%lld", &t[i]);
    s[0] = s[1], t[0] = t[1];
    s[a + 1] = s[a], t[b + 1] = t[b];
    while(q--) {
        scanf("%lld", &dd);

        int cnt1 = upper_bound(s + 1, s + a + 1, dd) - s;
        cnt1 = a - cnt1 + 1; //s中有cnt1個比dd大的

        int cnt2 = upper_bound(t + 1, t + b + 1, dd) - t;
        cnt2 = b - cnt2 + 1; //t中有cnt2個比dd大的

        ll res = 0;
        ll ans1 = abs(dd - s[a - cnt1]);
        ll ans2 = abs(dd - s[a - cnt1 + 1]);
        ll res1 = abs(s[a - cnt1] - t[b - cnt2]);
        ll res2 = abs(s[a - cnt1 + 1] - t[b - cnt2]);
        res = min(ans1 + res1, ans2 + res2);

        ans1 = abs(dd - s[a - cnt1]);
        ans2 = abs(dd - s[a - cnt1 + 1]);
        res1 = abs(s[a - cnt1] - t[b - cnt2 + 1]);
        res2 = abs(s[a - cnt1 + 1] - t[b - cnt2 + 1]);
        ll tmp1 = min(ans1 + res1, ans2 + res2);
        res = min(res, tmp1);

        ans1 = abs(dd - t[b - cnt2]);
        ans2 = abs(dd - t[b - cnt2 + 1]);
        res1 = abs(t[b - cnt2] - s[a - cnt1]);
        res2 = abs(t[b - cnt2 + 1] - s[a - cnt1]);
        ll tmp2 = min(ans1 + res1, ans2 + res2);
        res = min(res, tmp2);

        ans1 = abs(dd - t[b - cnt2]);
        ans2 = abs(dd - t[b - cnt2 + 1]);
        res1 = abs(t[b - cnt2] - s[a - cnt1 + 1]);
        res2 = abs(t[b - cnt2 + 1] - s[a - cnt1 + 1]);
        ll tmp3 = min(ans1 + res1, ans2 + res2);

        res = min(res, tmp3);
        cout << res << endl;
    }
}

 

<At-122C> GeT AC

題意:

給一個長度爲n的串s,q個查詢輸入L和R,問你在s[L]到s[R]之間,出現多少次捆綁的"AC"。

思路:

所求即爲當前輸入的R之前出現的AC的個數減去L之前出現的AC的個數即可,那麼二分搞一下就ok了。

先將所有捆綁出現的AC的A的位置存進pos數組中,然後

int cntr = lower_bound(pos + 1, pos + tot + 1, r) - pos; //pos中第一個大於等於r的下標

這樣得出第一個大於等於R的AC的pos的下標(pos的下標表示AC出現的個數),即超過R的第一個AC以及之前出現的AC個數,故cntr--,就得到R之前出現AC的次數。

同理

int cntl = lower_bound(pos + 1, pos + tot + 1, l) - pos; //pos中第一個大於等於l的下標

cntl--得到L之前出現的AC的個數

cntr - cntl 就是答案。

我的AC代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx = 1e5 + 22;
const int Inf = 1 << 30;
const ll INF = 1ll << 60;
priority_queue <int> qua;
vector <int> vec;
int n, q;
char s[maxx];
int l, r;
int pos[maxx];
 
int main() {
    scanf("%d %d", &n, &q);
    scanf("%s", s + 1);
    s[n + 1] = 'A', s[n + 2] = 'C';
    int tot = 0;
    for(int i = 1; i < n + 2; i++) {
        if(s[i] == 'A' && s[i + 1] == 'C') pos[++tot] = i;
    }
    while(q--) {
        scanf("%d %d", &l, &r);
        int cntr = lower_bound(pos + 1, pos + tot + 1, r) - pos; //pos中第一個大於等於r的下標
        cntr--; //r之前AC的個數
        int cntl = lower_bound(pos + 1, pos + tot + 1, l) - pos; //pos中第一個大於等於l的下標
        cntl--; //l之前AC的個數
        //printf("%d %d\n", cntl, cntr);
        printf("%d\n", cntr - cntl);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章