题解
Step1:单调栈处理
利用单调栈维护一个严格递减的下标栈,目的是未来在线性时间内求出每个点右侧比它大的最近位置,即:
void init_nxt() {
for (int i = n; i >= 1; i --) {
while(!st.empty() && d[st.top()] <= d[i]) {
st.pop();
}
up[i][0] = st.empty() ? 0 : st.top();
sum[i][0] = up[i][0] ? 1ll * c[up[i][0]] : 0ll;
st.push(i);
}
}Step2:链上倍增跳
为了把单次查询做到,我们对每个采用倍增预处理:
:从出发沿连走步后到达的结点。
:与之对应的这个结点容量的总和(不包括本身)
初始化:
void init_lift() {
for (int k = 1; k < LOGN; k ++) {
for (int i = 1; i <= n; i ++) {
int mid = up[i][k - 1]; // 先跳2^(k-1)步
if (mid) {
up[i][k] = up[mid][k - 1];
sum[i][k] = sum[i][k - 1] + sum[mid][k - 1];
} else {
up[i][k] = 0;
sum[i][k] = sum[i][k - 1];
}
}
}
}Step3: 单次查询处理
若首次盘的容积够大,能装满水,就直接返回
否则,从大到小枚举倍增系数,不断循环处理直至不能再跳为止,便找到答案。
ll query(int r, int v) {
if (c[r] >= v) {
return r;
}
v -= c[r];
for (int k = LOGN - 1; k >= 0; k --) {
if (up[r][k] && sum[r][k] < v) {
v -= sum[r][k];
r = up[r][k];
}
}
return up[r][0];
}完整代码
时间复杂度:
空间复杂度:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int LOGN = 20;
int n, q;
int d[N], c[N];
int up[N][LOGN];// up[i][k]:从 i 出发沿 nxt 走 2^k 步到达的节点
ll sum[N][LOGN];// sumv[i][k]:对应这 2^k 段的容量总和(不含 i 自身)
stack<int> st;
void init_nxt() {
for (int i = n; i >= 1; i --) {
while(!st.empty() && d[st.top()] <= d[i]) {
st.pop();
}
up[i][0] = st.empty() ? 0 : st.top();
sum[i][0] = up[i][0] ? 1ll * c[up[i][0]] : 0ll;
st.push(i);
}
}
void init_lift() {
for (int k = 1; k < LOGN; k ++) {
for (int i = 1; i <= n; i ++) {
int mid = up[i][k - 1]; // 先跳2^(k-1)步
if (mid) {
up[i][k] = up[mid][k - 1];
sum[i][k] = sum[i][k - 1] + sum[mid][k - 1];
} else {
up[i][k] = 0;
sum[i][k] = sum[i][k - 1];
}
}
}
}
ll query(int r, int v) {
if (c[r] >= v) {
return r;
}
v -= c[r];
for (int k = LOGN - 1; k >= 0; k --) {
if (up[r][k] && sum[r][k] < v) {
v -= sum[r][k];
r = up[r][k];
}
}
return up[r][0];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
for (int i = 1; i <= n; i ++) {
cin >> d[i] >> c[i];
}
init_nxt();
init_lift();
while(q --) {
int r, v;
cin >> r >> v;
cout << query(r, v) << endl;
}
return 0;
}
原创
洛谷P7167 Fountain
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法