传送门:HDU-6107
题解:ST算法
整片文章可以被分成2部分:①中间没有图片的部分;②中间插有图片的部分
可以将这2部分分别用ST离线,f[i][j]表示以第i个单词开始,连续1<<j行能写多少单词。要注意的是:在第②部分中,如果第一个单词的宽度大于dw和w-pw-dw的话,那么这一段f[i][j]=0
#include<bits/stdc++.h>
#define FIN freopen("in.txt","r",stdin);
using namespace std;
typedef long long LL;
const int MX = 1e5 + 5;
const int inf = 0x3f3f3f3f;
int mx, n, w, dw, pw, a[MX];
int f1[MX][30]; //从第i个开始,占用1<<j行能容下的字符
int f2[MX][30];
void ST() {
for (int i = 1; i <= n; i++) {
int cnt = a[i], j = i + 1;
while (cnt + a[j] + 1 <= w && j <= n) cnt += a[j++] + 1;
f1[i][0] = j - i;
}
for (int j = 1; (1 << j) <= mx; j++) {
for (int i = 1; i <= n; i++) {
f1[i][j] = f1[i][j - 1] + f1[i + f1[i][j - 1]][j - 1];
}
}
for (int i = 1; i <= n; i++) {
int cnt = 0, j = i, flag = 0;
while (cnt + a[j] + flag <= dw) cnt += a[j++] + flag, flag = 1;
int k = j;
cnt = flag = 0;
while (cnt + a[k] + flag <= w - pw - dw) cnt += a[k++] + flag, flag = 1;
f2[i][0] = k - i;
}
for (int j = 1; (1 << j) <= mx; j++) {
for (int i = 1; i <= n; i++) {
if (f2[i][j - 1] == 0) f2[i][j] = 0;
else f2[i][j] = f2[i][j - 1] + f2[i + f2[i][j - 1]][j - 1];
}
}
}
int RMQ1(int i, int x) {
if (x == 0) return i;
while (x && i <= n) {
int j = 0;
while ((1 << (j + 1)) <= x) j++;
i += f1[i][j];
x -= (1 << j);
}
return i;
}
int RMQ2(int i, int x) {
if (x == 0) return i;
while (x && i <= n) {
int j = 0;
while ((1 << (j + 1)) <= x) j++;
i += f2[i][j];
x -= (1 << j);
}
return i;
}
int RMQ3(int i) {
int ret = 0;
while (i <= n) {
int j = 0;
while (i + f1[i][j + 1] <= n) j++;
i += f1[i][j];
ret += (1 << j);
}
return ret;
}
struct Query {
int x, h;
} q[MX];
int main() {
//FIN;
int T, m;
scanf("%d", &T);
while (T--) {
scanf("%d%d%d%d", &n, &w, &pw, &dw);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
mx = n;
for (int i = 1; i <= m; i++) scanf("%d%d", &q[i].x, &q[i].h), mx = max(mx, n + q[i].x + q[i].h);
ST();
for (int i = 1; i <= m; i++) {
int x = q[i].x, h = q[i].h;
int tmp = RMQ3(1);
if (tmp <= x - 1) {
printf("%d\n", tmp + h);
continue;
}
int ans = x + h - 1;
int p = RMQ1(1, x - 1);
p = RMQ2(p, h);
if (p <= n) ans += RMQ3(p);
printf("%d\n", ans);
}
}
return 0;
}