L.(附加题)Sneakers(线段树板子题-完全体)

Sneakers

Description

有一天喜欢买鞋的ppq和小伙伴来到了某一家球鞋店,球鞋店有n种球鞋,价格分别为ai,ppq在鞋店兜兜转转,发现鞋店老板会偶尔将某段区间内球鞋的价格增加或减少,或者将某双球鞋的价格由价格A修改至价格B,机智的ppq将这些信息记录下来,可是ppq不会数数,所以他向机智的ACMer们求助,请帮助ppq完成以下m次操作,并得到ppq询问的结果。

有以下6种操作:

操作1:鞋店老板将下标位于【L,R】区间的球鞋的价格增加k。(无良老板)

操作2:鞋店老板将下标位于【L,R】区间的球鞋的价格减少k。(良心老板)

操作3: 鞋店老板将下标为pos的球鞋的价格修改为bi

操作4:ppq想买下标位于【L,R】区间内最贵的球鞋,询问他需要花费多少钱

操作5:ppq想买下标位于【L,R】区间内最便宜的球鞋,询问他需要花费多少钱

操作6:ppq想买下标位于【L,R】区间内所有的球鞋,询问他需要花费多少钱

Input

第一行输入n和q(n∈[1,300000],q∈[1,300000])

接下来一行n个数ai,表示第i种球鞋的价格,(ai∈[0,100000]) (因为可能是限量球鞋所以特别贵,滑稽)

接下来q行操作:

q1 L R k 表示将区间[L,R] 内的球鞋价格增加k元 (k∈[0,100000],1<=L<R<=n)

q2 L R k 表示将区间[L,R]内的球鞋价格减少k元 (k∈[0,100000],1<=L<R<=n)

q3 pos b表示将第pos双鞋的价格修改为b (pos∈[1,n],b∈[0,1000000],1<=pos<=n)

q4 L R 表示询问区间[L,R]内最贵的球鞋(1<=L<R<=n)

q5 L R 表示询问区间[L,R]内最便宜的球鞋(1<=L<R<=n)

q6 L R表示询问区间[L,R]内球鞋的价格之和(1<=L<R<=n)

Output

输出每次询问的答案(请注意答案可能为负数)

Sample Input 1

3 9
1 2 3
q4 1 3
q1 1 3 1
q5 1 3
q2 1 3 1
q6 1 3
q3 1 5
q4 1 3
q5 1 3
q6 1 3
Sample Output 1

3
2
6
5
2
10


这一题可以说是J题的进化版,它概括了线段树所有的基本操作,所以,我觉得这算得上是线段树的完全体了emmm。。。。
接下来就是套板子了。。

#include<cstdio>
#include<cstring>
#define debug(n) printf("%lld ",n)
#define ll long long
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define mac 300050
struct st {
	ll l,r;
	ll w,f,minn,maxx;
} tree[mac*4];
ll l,r,k;
ll ans=0,Min,Max;
void build(ll now,ll l,ll r);
void lazy(ll now);
void change(ll now,ll id);
void change_pot(ll now);
void ask(ll now);
void ask1(ll now);
int main() {
	ll n,q;
	scanf ("%lld%lld",&n,&q);
	build(1,1,n);
	char s[5];
	for (ll i=1; i<=q; i++) {
		scanf ("%s",s);
		Max=-999999999999999999;
		Min=999999999999999999;
		if (s[1]=='1') {
			scanf ("%lld%lld%lld",&l,&r,&k);
			change(1,1);
		} else if(s[1]=='2') {
			scanf ("%lld%lld%lld",&l,&r,&k);
			change(1,0);
		} else if(s[1]=='3') {
			scanf ("%lld%lld",&l,&k);
			change_pot(1);
		} else if (s[1]=='4') {
			scanf ("%lld%lld",&l,&r);
			ask1(1);
			printf ("%lld\n",Max);
		} else if (s[1]=='5') {
			scanf ("%lld%lld",&l,&r);
			ask1(1);
			printf ("%lld\n",Min);
		} else {
			scanf ("%lld%lld",&l,&r);
			ans=0;
			ask(1);
			printf ("%lld\n",ans);
		}
	}
	return 0;
}
void build(ll now,ll l,ll r) {
	tree[now].r=r,tree[now].l=l;
	if (l==r) {
		scanf ("%lld",&tree[now].w);
		tree[now].maxx=tree[now].minn=tree[now].w;
		return;
	}
	ll mid=(l+r)>>1;
	build (now*2,l,mid);
	build (now*2+1,mid+1,r);
	tree[now].w=tree[now*2].w+tree[now*2+1].w;
	tree[now].maxx=max(tree[now*2].maxx,tree[now*2+1].maxx);
	tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn);
}
void lazy(ll now) {
	tree[now*2].f+=tree[now].f;
	tree[now*2+1].f+=tree[now].f;
	tree[now*2].w+=tree[now].f*(tree[now*2].r-tree[now*2].l+1);
	tree[now*2+1].w+=tree[now].f*(tree[now*2+1].r-tree[now*2+1].l+1);
	tree[now*2].maxx+=tree[now].f;
	tree[now*2+1].maxx+=tree[now].f;
	tree[now*2].minn+=tree[now].f;
	tree[now*2+1].minn+=tree[now].f;
	tree[now].f=0;
}
void change(ll now,ll id) {
	if (tree[now].l>=l && tree[now].r<=r) {
		if (!id) {
			tree[now].w-=(tree[now].r-tree[now].l+1)*k;
			tree[now].f-=k;
			tree[now].maxx-=k;
			tree[now].minn-=k;
		} else {
			tree[now].w+=(tree[now].r-tree[now].l+1)*k;
			tree[now].f+=k;
			tree[now].maxx+=k;
			tree[now].minn+=k;
		}
		return;
	}
	if (tree[now].f) lazy(now);
	ll mid=(tree[now].l+tree[now].r)>>1;
	if (l<=mid) change(now*2,id);
	if (r>mid) change(now*2+1,id);
	tree[now].w=tree[now*2].w+tree[now*2+1].w;
	tree[now].maxx=max(tree[now*2].maxx,tree[now*2+1].maxx);
	tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn);
}
void change_pot(ll now) {
	if (tree[now].l==tree[now].r) {
		tree[now].w=k;
		tree[now].maxx=tree[now].minn=k;
		return;
	}
	if (tree[now].f) lazy(now);
	ll mid=(tree[now].l+tree[now].r)>>1;
	if (l<=mid) change_pot(now*2);
	else change_pot(now*2+1);
	tree[now].w=tree[now*2].w+tree[now*2+1].w;
	tree[now].maxx=max(tree[now*2].maxx,tree[now*2+1].maxx);
	tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn);
}
void ask(ll now) {
	if (tree[now].l>=l && tree[now].r<=r) {
		ans+=tree[now].w;
		return;
	}
	if (tree[now].f) lazy(now);
	ll mid=(tree[now].l+tree[now].r)>>1;
	if (l<=mid) ask(now*2);
	if (r>mid) ask(now*2+1);
}
void ask1(ll now) {
	if (tree[now].l>=l && tree[now].r<=r) {
		Max=max(tree[now].maxx,Max);
		Min=min(tree[now].minn,Min);
		return;
	}
	if (tree[now].f) lazy(now);
	ll mid=(tree[now].l+tree[now].r)>>1;
	if (l<=mid) ask1(now*2);
	if (r>mid) ask1(now*2+1);
}

猜你喜欢

转载自blog.csdn.net/qq_43906000/article/details/88264088