您的位置:首页 > 产品设计 > UI/UE

Gorgeous Sequence

2015-11-26 15:54 411 查看

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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: