2019.02.27【SCOI2018】Pipi 酱的日常(线段树)(有事没事循环展开)

描述

给定 n 个数,第 i(1<=i<=n)个位置上的值为xi,有 m 个操作分为两种操作:

将 x 数组位置 pos 上的数字改为 v

如果选择 x 数组[L,R]中的某连续三个数加 u,新得到的数组称为 y,求所有 可能形成的 y 数组的各元素绝对值之和的最大值(操作 2 不会改变 x 数组)。

输入

第一行输入 n 和 m,接下来一行,有 n 个数表示 x 数组;接下来 m 行,每行先 有一个数 op 表示操作为哪种操作,如果是 1,接下来两个数表示 pos, v;

如果是 2,接下来三个数表示 L, R, u。

输出

对于每个操作 2 输出答案。

样例输入

5 3
-2 -1 0 1 2
2 1 5 1
1 3 1
2 2 5 -1

样例输出

9
6

提示

对于 30%的数据有 3<=n,m<=1000。

对于 60%的数据有 3<=n,m<=30000。

对于 100%的数据有 3<=n,m<=100000, 1<=pos<=n, 1<=L<R<=n,R-L>=2,

1<=op<=2,其他未说明变量保证在整型范围内

【样例解释】

第一次操作可以得到的数组 y 有 3 种:

[-1, 0, 1, 1, 2], [-2, 0, 1, 2, 2], [-2, -1, 1, 2, 3] 其中绝对值的和最大的是[-2, -1, 1, 2, 3]为 9;

第二次操作将数组 x 改为[-2, -1, 1, 1, 2];

第三次操作可以得到的数组 y 有 2 种: [-2, -2, 0, 0, 2], [-2, -1, 0, 0, 1] 其中绝对值的和最大的是[-2, -2, 0, 0,2]


解析:

我们发现三元组分别取正负一共只有8种情况。

( a , b , c ) → a b s ( a + v ) + a b s ( b + v ) + a b s ( c + v ) (a,b,c)\rightarrow abs(a+v)+abs(b+v)+abs(c+v) (a,b,c)abs(a+v)+abs(b+v)+abs(c+v)
+ a + v + b + v + c + v = a + b + c + 3 v − a − v + b + v + c + v = − a + b + c + v + a + v − b − v + c + v = a − b + c + v − a − v − b − v + c + v = − a − b + c − v + a + v + b + v − c − v = a + b − c + v − a − v + b + v − c − v = − a + b − c − v + a + v − b − v − c − v = a − b − c − v − a − v − b − v − c − v = − a − b − c − 3 v \begin{aligned} +a+v+b+v+c+v&amp;=&amp;a+b+c+3v\\-a-v+b+v+c+v&amp;=&amp;-a+b+c+v\\+a+v-b-v+c+v&amp;=&amp;a-b+c+v\\-a-v-b-v+c+v&amp;=&amp;-a-b+c-v\\+a+v+b+v-c-v&amp;=&amp;a+b-c+v\\-a-v+b+v-c-v&amp;=&amp;-a+b-c-v\\+a+v-b-v-c-v&amp;=&amp;a-b-c-v\\-a-v-b-v-c-v&amp;=&amp;-a-b-c-3v \end{aligned} +a+v+b+v+c+vav+b+v+c+v+a+vbv+c+vavbv+c+v+a+v+b+vcvav+b+vcv+a+vbvcvavbvcv========a+b+c+3va+b+c+vab+c+vab+cva+bc+va+bcvabcvabc3v

我们发现其实取abs之和的结果就是这8个式子的最大值。

所以我们分别维护这8个变量就行了。

其实这道题的数据怎么出都卡不了常数,但是我闲得无聊写了一发循环展开。。。

然后就校内OJrk1了。

原来的rk1还是在数据加强之前上去的。。。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
	inline char get_char(){
		static cs int Rlen=1<<20|1;
		static char buf[Rlen],*p1,*p2;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline ll getint(){
		re char c;
		re bool f=0;
		while(!isdigit(c=gc()))if(c=='-')f=1;re ll num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return f?-num:num;
	}
}
using namespace IO;

cs int N=1e5+5;
cs ll INF=0x3f3f3f3f3f3f;

int n,m;
ll a[N];
ll mx[N<<2][8];
ll add[N<<2],ans[8];
ll sum;
int coef[8]={3,1,1,-1,1,-1,-1,-3};//0 + 1 - 

inline void init(int k,int pos){
	ll *A=a+pos,*B=mx[k];
	ll tmp=sum-abs(A[0])-abs(A[1])-abs(A[2]);
	B[0]=tmp+A[0]+A[1]+A[2];
	B[1]=tmp-A[0]+A[1]+A[2];
	B[2]=tmp+A[0]-A[1]+A[2];
	B[3]=tmp-A[0]-A[1]+A[2];
	B[4]=tmp+A[0]+A[1]-A[2];
	B[5]=tmp-A[0]+A[1]-A[2];
	B[6]=tmp+A[0]-A[1]-A[2];
	B[7]=tmp-A[0]-A[1]-A[2];
}

inline void pushup(int k){
	ll *K=mx[k],*lc=mx[k<<1],*rc=mx[k<<1|1];
	K[0]=max(lc[0],rc[0]);
	K[1]=max(lc[1],rc[1]);
	K[2]=max(lc[2],rc[2]);
	K[3]=max(lc[3],rc[3]);
	K[4]=max(lc[4],rc[4]);
	K[5]=max(lc[5],rc[5]);
	K[6]=max(lc[6],rc[6]);
	K[7]=max(lc[7],rc[7]);
}

inline void pushnow(int k,ll val){
	add[k]+=val;
	ll *K=mx[k];
	K[0]+=val;K[1]+=val;
	K[2]+=val;K[3]+=val;
	K[4]+=val;K[5]+=val;
	K[6]+=val;K[7]+=val;
}

inline void pushdown(int k){
	if(add[k]){
		pushnow(k<<1,add[k]);
		pushnow(k<<1|1,add[k]);
		add[k]=0;
	}
}

inline void build(int k,cs int &l,cs int &r){
	if(l==r)return init(k,l);
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
}

inline void update(int k,cs int &l,cs int &r,cs int &ql,cs int &qr){
	if(l==r)return init(k,l);
	pushdown(k);
	int mid=(l+r)>>1;
	if(ql<=mid)update(k<<1,l,mid,ql,qr);
	if(mid<qr)update(k<<1|1,mid+1,r,ql,qr);
	pushup(k);
}

inline void modify(int k,cs int &l,cs int &r,cs int &ql,cs int &qr,cs ll &val){
	if(ql<=l&&r<=qr)return pushnow(k,val);
	pushdown(k);
	int mid=(l+r)>>1;
	if(ql<=mid)modify(k<<1,l,mid,ql,qr,val);
	if(mid<qr)modify(k<<1|1,mid+1,r,ql,qr,val);
	pushup(k);
}

inline void get_ans(int k){
	ll *K=mx[k];
	ans[0]=max(ans[0],K[0]);
	ans[1]=max(ans[1],K[1]);
	ans[2]=max(ans[2],K[2]);
	ans[3]=max(ans[3],K[3]);
	ans[4]=max(ans[4],K[4]);
	ans[5]=max(ans[5],K[5]);
	ans[6]=max(ans[6],K[6]);
	ans[7]=max(ans[7],K[7]);
}

inline void query(int k,cs int &l,cs int &r,cs int &ql,cs int &qr){
	if(ql<=l&&r<=qr)return get_ans(k);
	pushdown(k);
	int mid=(l+r)>>1;
	if(ql<=mid)query(k<<1,l,mid,ql,qr);
	if(mid<qr)query(k<<1|1,mid+1,r,ql,qr);
}

inline ll getans(ll v){
	ll res=-INF;
	res=max(res,ans[0]+(ll)v*coef[0]);
	res=max(res,ans[1]+(ll)v*coef[1]);
	res=max(res,ans[2]+(ll)v*coef[2]);
	res=max(res,ans[3]+(ll)v*coef[3]);
	res=max(res,ans[4]+(ll)v*coef[4]);
	res=max(res,ans[5]+(ll)v*coef[5]);
	res=max(res,ans[6]+(ll)v*coef[6]);
	res=max(res,ans[7]+(ll)v*coef[7]);
	return res;
}

signed main(){
	n=getint();m=getint();
	for(int re i=1;i<=n;++i)sum+=abs(a[i]=getint());
	build(1,1,n-2);
	while(m--){
		switch(getint()){
			case 1:{
				int pos=getint();
				ll v=getint();
				ll delta=abs(v)-abs(a[pos]);
				sum+=delta;
				a[pos]=v;
				update(1,1,n-2,pos-2,pos);
				if(pos>3)modify(1,1,n-2,1,pos-3,delta);
				if(pos<n-2)modify(1,1,n-2,pos+1,n-2,delta);
				break;
			}
			case 2:{
				int l=getint(),r=getint();
				ll v=getint();
				memset(ans,-INF,sizeof ans);
				query(1,1,n-2,l,r-2);
				cout<<getans(v)<<"\n";
				break;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值