题目:https://www.luogu.com.cn/problem/P7167
题解:
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int d[N], c[N];
int ne[N][31], sum[N][31];//ne[i][j]代表i个位置往后数2^j位置后的下标
int st[N], t;
int n, q;
void init()
{
for (int i = 1; i <= n; i++)
{
sum[i][0] = c[i];
}
for (int i = 1; i <= 23; i++)
{
for (int j = 1; j <= n; j++)
{
ne[j][i] = ne[ne[j][i - 1]][i - 1];//建立一个递推式
}
}
for (int i = 1; i <= 23; i++)
{
for (int j = 1; j <= n; j++)
{
sum[j][i] = sum[j][i - 1] + sum[ne[j][i - 1]][i - 1];
}
}
}
int main()
{
cin >> n >> q;
for (int i = 1; i <= n; i++) { cin >> d[i] >> c[i]; }//输入对应的半径和容量
for (int i = n; i >= 1; i--)//从后往前
{
while (t && d[st[t]] <= d[i]) { t--; }//单调栈
ne[i][0] = st[t];
st[++t] = i;
}
init();
while (q--)
{
int a, b;
cin >> a >> b;
for (int i = 23; i >= 0; i--)//从大区间进行搜索
{
if (sum[a][i] < b)
{
b -= sum[a][i];
a = ne[a][i];//逐渐缩小到小区间
}
}
cout << a << endl;
}
}