题解 求和
发现一次修改影响的东西太多了所以几乎什么都不能维护
所以缩小有用的点集
发现可以将有用的点约束到 \(\forall j\in[i-k, i-1], a_j\leqslant a_i \and \forall j\in[i+1, i+k], a_j< a_i\) 的 \(i\)
于是发现在每次修改的时候影响到的点变成了常数个
讨论是不是特殊点及修改后特殊点是否变化即可
复杂度 \(O(n\log n)\),需要卡常
- 一切线段树单点修改都可以很方便地非递归实现
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define fir first
#define sec second
#define ll long long
// #define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k, q, op;
int a[N];
namespace task{
bool vis[N];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define mx(p) mx[p]
#define val(p) val[p]
#define pos(p) pos[p]
#define max(a, b) ((a)>(b)?(a):(b))
#define min(a, b) ((a)<(b)?(a):(b))
int tl[N<<2], tr[N<<2], pos[N<<2], val[N<<2], bkp[N], que[N], ql, qr;
// inline void pushup(int p) {
// mx(p)=max(mx(p<<1), mx(p<<1|1));
// pos(p)=mx(p)==mx(p<<1|1)?pos(p<<1|1):pos(p<<1);
// }
inline void pushup(int p) {
p=bkp[p]>>1;
for (; p; p>>=1) pos(p)=a[pos(p<<1|1)]>=a[pos(p<<1)]?pos(p<<1|1):pos(p<<1);
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) {bkp[l]=p; pos(p)=l; return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
// pushup(p);
pos(p)=a[pos(p<<1|1)]>=a[pos(p<<1)]?pos(p<<1|1):pos(p<<1);
}
// void upd(int p, int pos) {
// if (tl(p)==tr(p)) return ;
// int mid=(tl(p)+tr(p))>>1;
// if (pos<=mid) upd(p<<1, pos, dat);
// else upd(p<<1|1, pos, dat);
// // pushup(p);
// pos(p)=a[pos(p<<1|1)]>=a[pos(p<<1)]?pos(p<<1|1):pos(p<<1);
// }
int query(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return pos(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid&&r>mid) {
int u=query(p<<1, l, r);
int v=query(p<<1|1, l, r);
return a[u]>a[v]?u:v;
}
else if (l<=mid) return query(p<<1, l, r);
else return query(p<<1|1, l, r);
}
// void upd2(int p, int pos, int dat) {
// if (tl(p)==tr(p)) {val(p)=dat; return ;}
// int mid=(tl(p)+tr(p))>>1;
// if (pos<=mid) upd2(p<<1, pos, dat);
// else upd2(p<<1|1, pos, dat);
// val(p)=max(val(p<<1), val(p<<1|1));
// }
inline void upd2(int useless, int p, int dat) {
p=bkp[p]; val(p)=dat;
for (p>>=1; p; p>>=1) val(p)=max(val(p<<1), val(p<<1|1));
}
int query2(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return val(p);
int mid=(tl(p)+tr(p))>>1, ans=0;
if (l<=mid) ans=max(ans, query2(p<<1, l, r));
if (r>mid) ans=max(ans, query2(p<<1|1, l, r));
return ans;
}
void check(int i) {
if (i<1 || i>n) return ;
int l=query(1, max(i-k, 0), i-1);
int r=query(1, i+1, min(i+k, n+1));
// cout<<"l: "<<l.fir<<' '<<l.sec<<endl;
// cout<<"r: "<<r.fir<<' '<<r.sec<<endl;
if (a[l]<=a[i] && a[i]>a[r]) vis[i]=1, upd2(1, i, a[i]+max(a[l], a[r]));
else if (vis[i]) vis[i]=0, upd2(1, i, 0);
}
void solve() {
int ans=0;
build(1, 0, n+1);
// seg2::build(1, 1, n);
// for (int i=1; i<=n; ++i) check(i);
ql=1; qr=1;
for (int i=1; i<=n; ++i) {
while (ql<=qr && que[ql]<i-k) ++ql;
int l=que[ql];
int r=query(1, i+1, min(i+k, n+1));
if (a[l]<=a[i] && a[i]>a[r]) vis[i]=1, upd2(1, i, a[i]+max(a[l], a[r]));
else if (vis[i]) vis[i]=0, upd2(1, i, 0);
while (ql<=qr && a[que[qr]]<=a[i]) --qr;
que[++qr]=i;
}
// cout<<"vis: "; for (int i=1; i<=n; ++i) cout<<vis[i]<<' '; cout<<endl;
printf("%d\n", ans=val(1));
for (int i=1,x,y,l,r; i<=q; ++i) {
// cout<<"i: "<<i<<endl;
x=read()^(ans*op); y=read()^(ans*op);
// cout<<"xy: "<<x<<' '<<y<<endl;
// upd(1, x, a[x]=y);
a[x]=y; pushup(x);
l=query(1, max(x-k, 0), x-1);
r=query(1, x+1, min(x+k, n+1));
if (vis[x]) {
if (a[l]<=y && y>a[r]) upd2(1, x, y+max(a[l], a[r]));
else {
vis[x]=0;
upd2(1, x, 0);
if (a[l]>y) check(l);
if (a[r]>=y) check(r);
}
}
else {
if (a[l]<=y && y>a[r]) vis[x]=1, upd2(1, x, y+max(a[l], a[r]));
else {
if (a[l]>y) check(l);
if (a[r]>=y) check(r);
}
}
printf("%d\n", ans=val(1));
}
}
}
signed main()
{
freopen("sum.in", "r", stdin);
freopen("sum.out", "w", stdout);
n=read(); k=read(); q=read(); op=read();
for (int i=1; i<=n; ++i) a[i]=read();
task::solve();
return 0;
}