给一些互不包含的区间和一些石子堆,按顺序依次从区间内取走一些石子且每次有上限,要求每次都尽量取最多石子。
假设前面的
i−1
个区间全部满足了,且第
j
个区间取到了
时间复杂度
O(mlogm)
,但是不知道为什么在bzoj上跑的这么慢,明明只有4w的数据范围。。。
哦数据里好像有
m<2
的要特判一下。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = a, _ = b; i <= _; i ++)
const int inf = 0x3fffffff;
const int maxn = 40007;
const int maxs = (1 << 17) + 7;
typedef int seg[maxs];
typedef int arr[maxn];
#define T int u, int l, int r
#define L lc , l , m
#define R rc , m + 1 , r
#define lc (u << 1)
#define rc (u << 1 | 1)
seg mn, mx, s1, s2, tg1, tg2;
arr a, l, r, k, h;
int v1, v2, v, ql, qr;
int n, m;
bool cmp(const int i, const int j) {
return l[i] < l[j];
}
void upd(int u) {
mn[u] = min(mn[lc], mn[rc]);
mx[u] = max(mx[lc], mx[rc]);
}
void B(T) {
mn[u] = inf, mx[u] = -inf;
if (l == r) return;
int m = (l + r) >> 1;
B(L), B(R);
}
void tag1(int u, int v) {
mn[u] -= v, s1[u] += v, tg1[u] += v;
}
void tag2(int u, int v) {
mx[u] -= v, s2[u] += v, tg2[u] += v;
}
void push(int u) {
if (tg1[u]) {
tag1(lc, tg1[u]), tag1(rc, tg1[u]);
tg1[u] = 0;
}
if (tg2[u]) {
tag2(lc, tg2[u]), tag2(rc, tg2[u]);
tg2[u] = 0;
}
}
int get(T, int p) {
if (l == r) return s1[u];
int m = (l + r) >> 1; push(u);
return p <= m ? get(L, p) : get(R, p);
}
void que(T) {
if (ql <= l && r <= qr) {
v1 = min(v1, mn[u]);
v2 = max(v2, mx[u]);
return;
}
push(u);
int m = (l + r) >> 1;
if (ql <= m) que(L);
if (qr > m) que(R);
}
void gao(T, int p) {
if (l == r) {
mn[u] = a[::r[h[l]]] - s1[u];
mx[u] = a[::l[h[l]] - 1] - s2[u];
return;
}
int m = (l + r) >> 1;
push(u);
if (p <= m) gao(L, p); else gao(R, p);
upd(u);
}
void gao1(T) {
if (ql <= l && r <= qr) {
tag1(u, v);
return;
}
int m = (l + r) >> 1; push(u);
if (ql <= m) gao1(L);
if (qr > m) gao1(R);
upd(u);
}
void gao2(T) {
if (ql <= l && r <= qr) {
tag2(u, v);
return;
}
int m = (l + r) >> 1; push(u);
if (ql <= m) gao2(L);
if (qr > m) gao2(R);
upd(u);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int x, y, z, P;
scanf("%d", &n);
scanf("%d%d%d%d", &x, &y, &z, &P);
rep (i , 1 , n) a[i] = ((i - x) * (i - x) % P + (i - y) * (i - y) % P + (i - z) * (i - z) % P) % P, a[i] += a[i - 1];
//rep (i , 1 , n) cerr << a[i] << " "; cerr << endl;
scanf("%d", &m);
scanf("%d%d%d%d%d%d", &k[1], &k[2], &x, &y, &z, &P);
rep (i , 3 , m) k[i] = (x * k[i - 1] % P + y * k[i - 2] % P + z) % P;
rep (i , 1 , m) scanf("%d%d", &l[i], &r[i]);
if (m < 2) {
rep (i , 1 , m) printf("%d\n", min(a[r[i]] - a[l[i] - 1], k[i]));
return 0;
}
rep (i , 1 , m) h[i] = i;
B(1, 1, m);
static arr rk;
sort(h + 1, h + m + 1, cmp);
rep (i , 1 , m) rk[h[i]] = i;
rep (i , 1 , m) {
int l = ::l[i], r = ::r[i], k = ::k[i], p = rk[i];
int x = get(1, 1, m, p);
v1 = a[r] - x;
ql = p + 1, qr = m;
if (ql <= qr)
que(1, 1, m);
int tmp = v1;
v2 = a[l - 1] - x;
ql = 1, qr = p - 1;
if (ql <= qr)
que(1, 1, m);
v1 = tmp;
v = min(k, min(v1 - v2, a[r] - a[l - 1]));
printf("%d\n", v);
ql = p, qr = m;
gao1(1, 1, m);
ql = p + 1 , qr = m;
if (ql <= qr)
gao2(1, 1, m);
gao(1, 1, m, p);
}
return 0;
}