题意:
给你一个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
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;
}
}
题意:
给一个长度为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
using namespace std;
typedef long long ll;
const int maxx = 1e5 + 22;
const int Inf = 1 << 30;
const ll INF = 1ll << 60;
priority_queue
vector
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);
}
}