To_Heart—题解——内需消费

题目链接

题解

首先,我们先假设这道题不需要修改物价,那么我们如何找到最好的情况呢?

差分。如下数列:

1 4 3 5 2

很容易观察出,在第一个商店到第二个商店中,我们最多可以赚3元,在第一个商店进货,第二个商店卖出。

但是在第二个商店到第三个商店的途中,我们不能赚钱。因为第二个商店的价格比第三个商店的价格的价格大,所以最优的情况是不进行买卖操作。

所以我们第一个商店到第三个商店最多能赚多少呢?即是在第一个商店买,第二个商店卖,在第三个商店不进行操作。

那么对于第一个商店到第四个商店,最多赚4元。但4=3+0+1,即选择在第一个商店买,第二个商店又买又卖,第三个商店不进行操作,第四个商店又卖;

所以就是差分了。

定义a[i],存放每个商店的价格;

定义sum[i],表示由第i到i+1最多可以赚的钱数;

sum[i]=max(0,a[i+1]-a[i]);

因为如果a[i]>a[i+1],那么最优操作是不进行买卖,也就是赚0元。

最后的答案就是求差分数组的和了。

值得注意的是,在这道题中,从i走到j和从j走到i是不一样的意思的,所以需要两个差分数组;

对于差分数组,可以用线段树维护。

现在我们来想一下如何进行改变值的操作。

设:a[i]改变了,只会影响 a [ i ] − a [ i + 1 ] , a [ i + 1 ] − a [ i ] , a [ i ] − a [ i − 1 ] a[i] - a[i+1], a[i+1] - a[i],a[i] - a[i-1] a[i]a[i+1],a[i+1]a[i],a[i]a[i1]以及 a [ i − 1 ] − a [ i ] a[i-1] - a[i] a[i1]a[i]的值,所以我们只需要改变 i − 1 , i , i + 1 i-1,i,i+1 i1,i,i+1的差分值就可以了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define L(a) t[a].val_to_l
#define R(a) t[a].val_to_r

struct Segment_Tree{
    
    
	int l,r;
	ll val_to_l;
	ll val_to_r;
}t[4000005];


int n,m;
ll a[1000005];

void Build_Tree(int q,int l,int r){
    
    
	t[q].l=l;
	t[q].r=r;
	if(l==r){
    
    
		L(q)=max(0,a[l]-a[l-1]);
		R(q)=max(0,a[l]-a[l+1]);
		return;
	}
	int mid=(l+r)>>1;
	Build_Tree(q*2,l,mid);
	Build_Tree(q*2+1,mid+1,r);
	L(q)=L(q*2)+L(q*2+1);
	R(q)=R(q*2)+R(q*2+1);
}

void Change_Tree(int q,int x){
    
    
	if(x>n||x<1)	return ;
	if(t[q].l==t[q].r){
    
    
		L(q)=max(0,a[t[q].l]-a[t[q].l-1]);
		R(q)=max(0,a[t[q].l]-a[t[q].l+1]);
		return ;
	}
	int mid=(t[q].r+t[q].l)>>1;
	if(x<=mid){
    
    
		Change_Tree(q*2,x);
	}
	else{
    
    
		Change_Tree(q*2+1,x);
	}
	L(q)=L(q*2)+L(q*2+1);
	R(q)=R(q*2)+R(q*2+1);
}

ll Find_Tree(int p,int l,int r,int op){
    
    
	ll ans=0;
	if(t[p].l>=l&&t[p].r<=r){
    
    
		return op?R(p):L(p);
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid){
    
    
		ans+=Find_Tree(p*2,l,r,op);
	}
	if(mid<r){
    
    
		ans+=Find_Tree(p*2+1,l,r,op);
	}
	return ans;
}


void Put(){
    
    
	for(int i=1;i<=4*n;i++){
    
    
		printf("t[%d] %d %d %d %d\n",i,t[i].l,t[i].r,L(i),R(i));
	}
}

int main(){
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		scanf("%d",&a[i]);
	}
	Build_Tree(1,1,n);
	for(int i=1;i<=m;i++){
    
    
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op&1){
    
    
			if(x==y){
    
    	printf("0\n");}
			else if(x>y)	
				printf("%d\n",Find_Tree(1,y,x-1,1));
			else 
				printf("%d\n",Find_Tree(1,x+1,y,0));
		}
		else {
    
    
			a[x]=y;
			Change_Tree(1,x);
			Change_Tree(1,x-1);
			Change_Tree(1,x+1);
		}
//		Put();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xf2056188203/article/details/111588403