Gorgeous Sequence
时间限制: 3 Sec 内存限制: 128 MB
题目描述
有一个长为n的序列,第i个数为ai。对于这个序列有三种操作方式:
0 x y t:对于任意的x≤i≤y,用min(ai,t)替换原来的ai;
1 x y:输出[x,y]区间所有元素的最大值。
2 x y:输出[x,y]区间所有元素的和。
输入
第一行一个整数T,表示测试点的个数。
对于每个测试点:
第一行两个整数n和m,分别表示序列的长度和操作的次数。
第二行包含n个整数,a1,…,an (∀1≤i≤n,0≤ai<231)。
接下来m行,每行代表一次操作,其中(1≤x≤y≤n,0≤t<231)。
所有数据保证T=100, ∑n≤1000000, ∑m≤1000000。
输出
对于每个操作1或2,请输出相应查询的答案。
样例输入
1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5
样例输出
5
15
3
12
来源
hdu2015多校
题解
对于每次修改操作,在找到一个区间后将标记尽可能下传,直到一个区间内不会增加被修改的数字时才结束。
考虑复杂度,每个数字最多只会被标记一次,每次需要logn次操作。所以效率为nlogn。(瞎证明的,欢迎更科学的证明)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define N 1000010
#define ll long long
using namespace std;
int Q,n,m,s[N];
struct node{int maxn,num,lazy;ll sum;}t[N*4];
inline int get()
{
char ch;
while(!isdigit(ch=getchar()));
int v=ch-48;
while(isdigit(ch=getchar()))v=v*10+ch-48;
return v;
}
class seg_tree
{
inline void update(int x)
{
int lc=x<<1,rc=lc+1;
t[x].maxn=max(t[lc].maxn,t[rc].maxn);
t[x].sum=t[lc].sum+t[rc].sum;
t[x].num=t[lc].num+t[rc].num;
}
void work(int x,int l,int r,int num)
{
if(t[x].lazy<=num&&t[x].lazy)return;
t[x].lazy=num;t[x].sum+=(ll)(r-l+1-t[x].num)*num;
if(t[x].num<r-l+1)t[x].maxn=num,t[x].num=r-l+1;
}
inline void pushdown(int x,int l,int r)
{
if(!t[x].lazy)return;
int mid=l+r>>1,lc=x<<1,rc=lc+1;
work(lc,l,mid,t[x].lazy);
work(rc,mid+1,r,t[x].lazy);
t[x].lazy=0;
}
public:
inline void build(int x,int l,int r)
{
t[x].lazy=0;
if(l==r)
{
t[x].maxn=s[l];t[x].lazy=s[l];
t[x].sum=s[l];t[x].num=1;return;
}
int mid=l+r>>1,lc=x<<1,rc=lc+1;
build(lc,l,mid);build(rc,mid+1,r);
update(x);
}
inline void find(int x,int l,int r,int num)
{
if(t[x].maxn<=num)return;
if(t[x].lazy>num)t[x].lazy=0;
if(l==r)
{
t[x].maxn=t[x].lazy;t[x].sum=t[x].lazy;
t[x].num=t[x].lazy?1:0;return;
}
int mid=l+r>>1,lc=x<<1,rc=lc+1;
pushdown(x,l,r);
find(lc,l,mid,num);
find(rc,mid+1,r,num);
update(x);
}
inline void modify(int x,int l,int r,int ql,int qr,int num)
{
if(t[x].maxn<=num)return;
if(ql<=l&&r<=qr){find(x,l,r,num);work(x,l,r,num);return;}
int mid=l+r>>1,lc=x<<1,rc=lc+1;
pushdown(x,l,r);
if(ql<=mid)modify(lc,l,mid,ql,qr,num);
if(qr>mid)modify(rc,mid+1,r,ql,qr,num);
update(x);
}
inline int qry1(int x,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return t[x].maxn;
int mid=l+r>>1,lc=x<<1,rc=lc+1,res=0;
pushdown(x,l,r);
if(ql<=mid)res=max(res,qry1(lc,l,mid,ql,qr));
if(qr>mid)res=max(res,qry1(rc,mid+1,r,ql,qr));
return res;
}
inline ll qry2(int x,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return t[x].sum;
int mid=l+r>>1,lc=x<<1,rc=lc+1;ll res=0;
pushdown(x,l,r);
if(ql<=mid)res+=qry2(lc,l,mid,ql,qr);
if(qr>mid)res+=qry2(rc,mid+1,r,ql,qr);
return res;
}
}T;
int main()
{
int type,a,b,c;
Q=get();
while(Q--)
{
n=get();m=get();
for(int i=1;i<=n;i++)s[i]=get();
T.build(1,1,n);
for(int i=1;i<=m;i++)
{
type=get();a=get();b=get();
if(!type)c=get(),T.modify(1,1,n,a,b,c);
if(type==1)printf("%d\n",T.qry1(1,1,n,a,b));
if(type==2)printf("%lld\n",T.qry2(1,1,n,a,b));
}
}
return 0;
}