\(\text{Problem}\)
\(\text{Analysis}\)
为方便操作,我们把长度为 \(m\) 的环倍长,把修改 \(l < r\) 的 \(r\) 改为 \(r+m\)
而后就可以整体二分了
二分答案,把需要的修改放到树状数组,检查询问时一个一个枚举其所在位置,相应划分询问,继续二分
\(\text{Code}\)
#include<cstdio>
#define LL long long
using namespace std;
const int N = 3e5 + 5;
int n, m, cnt, p[N], h[N], ans[N];
struct node{
int ty, l, r, a, id;
}q[N * 2], q1[N * 2], q2[N * 2];
struct edge{
int to, nxt;
}e[N];
inline void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
}
inline void link(int x, int y)
{
static int tot = 0;
e[++tot] = edge{y, h[x]}, h[x] = tot;
}
LL c[N * 2];
inline int lowbit(int x){return x & (-x);}
inline void add(int x, int v){for(; x <= 2 * m; x += lowbit(x)) c[x] += v;}
inline LL query(int x)
{
LL ret = 0;
for(; x; x -= lowbit(x)) ret += c[x];
return ret;
}
void solve(int l, int r, int ql, int qr)
{
if (ql > qr) return;
if (l == r)
{
for(int i = ql; i <= qr; i++)
if (!q[i].ty) ans[q[i].l] = l;
return;
}
int mid = (l + r) >> 1, cnt1 = 0, cnt2 = 0;
for(int i = ql; i <= qr; i++)
{
if (q[i].ty == 1)
{
if (q[i].id <= mid) add(q[i].l, q[i].a), add(q[i].r + 1, -q[i].a), q1[++cnt1] = q[i];
else q2[++cnt2] = q[i];
}
else{
LL sum = 0;
for(int j = h[q[i].l]; j; j = e[j].nxt)
{
sum += query(e[j].to) + query(e[j].to + m);
if (sum >= q[i].r)
{
q1[++cnt1] = q[i];
break;
}
}
if (sum < q[i].r) q[i].r -= sum, q2[++cnt2] = q[i];
}
}
for(int i = 1; i <= cnt1; i++)
if (q1[i].ty == 1) add(q1[i].l, -q1[i].a), add(q1[i].r + 1, q1[i].a);
for(int i = 1; i <= cnt1; i++) q[ql + i - 1] = q1[i];
for(int i = 1; i <= cnt2; i++) q[ql + cnt1 + i - 1] = q2[i];
solve(l, mid, ql, ql + cnt1 - 1), solve(mid + 1, r, ql + cnt1, qr);
}
int main()
{
read(n), read(m);
for(int i = 1, x; i <= m; i++) read(x), link(x, i);
for(int i = 1; i <= n; i++) read(p[i]);
int k; read(k);
for(int i = 1, l, r, a; i <= k; i++)
{
read(l), read(r), read(a);
if (l > r) r += m;
q[++cnt] = node{1, l, r, a, i};
}
for(int i = 1; i <= n; i++) q[++cnt] = node{0, i, p[i]};
solve(1, k + 1, 1, cnt);
for(int i = 1; i <= n; i++)
{
if (ans[i] != k + 1) printf("%d\n", ans[i]);
else printf("NIE\n");
}
}