<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);
}
}