【BZOJ4355】Play with sequence 线段树

【BZOJ4355】Play with sequence

Description

维护一个长度为N的序列a,现在有三种操作:
1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a[V]都赋值为C。
2)给出参数U,V,C,对于区间[U,V]里的每个数i,将a[i]赋值为max(a[i]+C,0)。
3)给出参数U,V,输出a[U],a[U+1],...,a[V-1],a[V]里值为0的数字个数。

Input

第一行包含两个正整数N,M(1<=N,M<=300000),分别表示序列长度和操作个数。
第二行包含N个整数,其中第i个数表示a[i](0<=a[i]<=10^9),描述序列的初始状态。
接下来M行描述M个操作,保证1<=U<=V<=N,对于操作1,0<=C<=10^9,对于操作2,|C|<=10^9。

Output

输出若干行,每行一个整数,依次回答每个操作3的问题。

Sample Input

5 3
6 4 6 6 4
2 1 5 -5
1 3 4 4
3 1 5

Sample Output

2

题解:懒了直接粘题解+证明

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <utility>
#define lson x<<1
#define rson x<<1|1
#define mp(A,B) make_pair(A,B)
#define F first
#define S second
using namespace std;
const int maxn=300010;
typedef long long ll;
typedef pair<ll,int> pli;
const ll NON=123456789123456ll;
ll n1[maxn<<2],n2[maxn<<2],ts[maxn<<2],tc[maxn<<2],tn[maxn<<2];
int cnt[maxn<<2];
ll v[maxn];
int n,m;
inline void add(int x,int l,int r,ll v)
{
	n1[x]+=v,n2[x]+=v;
	if(tc[x]!=NON)	tc[x]+=v;
	else	ts[x]+=v;
	if(tn[x]!=NON)	tn[x]+=v;
}
inline void cov(int x,int l,int r,ll v)
{
	n1[x]=v,n2[x]=NON,cnt[x]=r-l+1,ts[x]=0,tc[x]=v,tn[x]=NON;
}
inline void con(int x,int l,int r,ll v)
{
	if(n1[x]<v)	n1[x]=v;
	if(tn[x]==NON||tn[x]<v)	tn[x]=v;
}
inline void pushup(int x)
{
	if(n1[lson]==n1[rson])	n1[x]=n1[lson],n2[x]=min(n2[lson],n2[rson]);
	else	if(n1[lson]<n1[rson])	n1[x]=n1[lson],n2[x]=min(n2[lson],n1[rson]);
	else	n1[x]=n1[rson],n2[x]=min(n1[lson],n2[rson]);
	cnt[x]=0;
	if(n1[x]==n1[lson])	cnt[x]+=cnt[lson];
	if(n1[x]==n1[rson])	cnt[x]+=cnt[rson];
}
inline void pushdown(int l,int r,int x)
{
	int mid=(l+r)>>1;
	if(ts[x])	add(lson,l,mid,ts[x]),add(rson,mid+1,r,ts[x]),ts[x]=0;
	if(tc[x]!=NON)	cov(lson,l,mid,tc[x]),cov(rson,mid+1,r,tc[x]),tc[x]=NON;
	if(tn[x]!=NON)	con(lson,l,mid,tn[x]),con(rson,mid+1,r,tn[x]),tn[x]=NON;
}
void upadd(int l,int r,int x,int a,int b,ll v)
{
	if(a<=l&&r<=b)
	{
		add(x,l,r,v);
		return ;
	}
	pushdown(l,r,x);
	int mid=(l+r)>>1;
	if(a<=mid)	upadd(l,mid,lson,a,b,v);
	if(b>mid)	upadd(mid+1,r,rson,a,b,v);
	pushup(x);
}
void upcov(int l,int r,int x,int a,int b,ll v)
{
	if(a<=l&&r<=b)
	{
		cov(x,l,r,v);
		return ;
	}
	pushdown(l,r,x);
	int mid=(l+r)>>1;
	if(a<=mid)	upcov(l,mid,lson,a,b,v);
	if(b>mid)	upcov(mid+1,r,rson,a,b,v);
	pushup(x);
}
void upcon(int l,int r,int x,int a,int b,ll v)
{
	if(a<=l&&r<=b)
	{
		if(v<=n1[x])	return ;
		if(v<n2[x])
		{
			con(x,l,r,v);
			return ;
		}
	}
	pushdown(l,r,x);
	int mid=(l+r)>>1;
	if(a<=mid)	upcon(l,mid,lson,a,b,v);
	if(b>mid)	upcon(mid+1,r,rson,a,b,v);
	pushup(x);
}
pli query(int l,int r,int x,int a,int b)
{
	if(a<=l&&r<=b)	return mp(n1[x],cnt[x]);
	pushdown(l,r,x);	
	int mid=(l+r)>>1;
	if(b<=mid)	return query(l,mid,lson,a,b);
	if(a>mid)	return query(mid+1,r,rson,a,b);
	pli sl=query(l,mid,lson,a,b),sr=query(mid+1,r,rson,a,b),ret;
	if(sl.F==sr.F)	ret.F=sl.F,ret.S=sl.S+sr.S;
	else	if(sl.F<sr.F)	ret=sl;
	else	ret=sr;
	return ret;
}
void build(int l,int r,int x)
{
	tc[x]=tn[x]=NON;
	if(l==r)
	{
		n1[x]=v[l],n2[x]=NON,cnt[x]=1;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,lson),build(mid+1,r,rson);
	pushup(x);
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd();
	int i,a,b,c,op;
	for(i=1;i<=n;i++)	v[i]=rd();
	build(1,n,1);
	for(i=1;i<=m;i++)
	{
		op=rd(),a=rd(),b=rd();
		if(op==1)	c=rd(),upcov(1,n,1,a,b,c);
		if(op==2)	c=rd(),upadd(1,n,1,a,b,c),upcon(1,n,1,a,b,0);
		if(op==3)
		{
			pli tmp=query(1,n,1,a,b);
			if(tmp.F)	puts("0");
			else	printf("%d\n",query(1,n,1,a,b).S);
		}
	}
	return 0;
}//4 3 9 5 7 4  1 3 3 2 2 1 3 -7 3 2 4
posted @ 2018-01-14 20:43  CQzhangyu  阅读(531)  评论(1编辑  收藏  举报