题解 求和

传送门

发现一次修改影响的东西太多了所以几乎什么都不能维护
所以缩小有用的点集
发现可以将有用的点约束到 \(\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;
}
posted @ 2022-03-14 21:43  Administrator-09  阅读(1)  评论(0编辑  收藏  举报