HDU5306 Gorgeous Sequence
Problem Description
There is a sequence a of length n. We use ai to denote the i-th element in this sequence. You should do the following three types of operations to this sequence.
0 x y t: For every x≤i≤y, we use min(ai,t) to replace the original ai’s value.
1 x y: Print the maximum value of ai that x≤i≤y.
2 x y: Print the sum of ai that x≤i≤y.
Input
The first line of the input is a single integer T, indicating the number of testcases.
The first line contains two integers n and m denoting the length of the sequence and the number of operations.
The second line contains n separated integers a1,…,an (∀1≤i≤n,0≤ai<231).
Each of the following m lines represents one operation (1≤x≤y≤n,0≤t<231).
It is guaranteed that T=100, ∑n≤1000000, ∑m≤1000000.
Output
For every operation of type 1 or 2, print one line containing the answer to the corresponding query.
Sample Input
1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5
Sample Output
5
15
3
12
问题描述
有一个长度为n的序列a。 我们用ai表示此序列中的第i个元素。 您应该对此序列执行以下三种类型的操作。
0 x y t:对于每个x≤i≤y,我们使用min(ai,t)替换原始ai的值。
1 x y:打印x≤i≤y的ai最大值。
2 x y:打印x≤i≤y的ai的总和。
输入
输入的第一行是单个整数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
分析
每个节点维护最大值max,次大值se,区间和sum,最大值个数cnt
区间取最小值操作ai=min(ai,t)
1.如果max<=t,那么不需要进行修改
2.如果se<t<max,那么需要更新区间中那些最大值,区间和sum+=cnt*(t-max)
3.如果t<=se,那么就向下递归操作,然后向上更新
注意:区间和会超int ,所以用long long
不过要是所有变量都用long long 定义,可能会超时
#include<bits/stdc++.h>
#define ll long long
#define a u<<1
#define b u<<1|1
using namespace std;
const int N=1e6+7,M=N*4;
inline int read()
{
register int s=0,w=1;
register char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return w*s;
}
int t,n,m;
int w[N];
int mx[M],se[M],cn[M],tag[M],le[M],ri[M];
ll sum[M];
void pushup(int u)
{
sum[u]=sum[a]+sum[b];
if(mx[a]==mx[b])
{
mx[u]=mx[a];
cn[u]=cn[a]+cn[b];
se[u]=max(se[a],se[b]);
}
else if(mx[a]>mx[b])
{
mx[u]=mx[a];
cn[u]=cn[a];
se[u]=max(se[a],mx[b]);
}
else
{
mx[u]=mx[b];
cn[u]=cn[b];
se[u]=max(mx[a],se[b]);
}
}
void pushdown(int u)
{
if(tag[u]!=-1)
{
if(mx[a]>tag[u])
{
sum[a]+=(ll)(tag[u]-mx[a])*cn[a];
mx[a]=tag[a]=tag[u];
}
if(mx[b]>tag[u])
{
sum[b]+=(ll)(tag[u]-mx[b])*cn[b];
mx[b]=tag[b]=tag[u];
}
tag[u]=-1;
}
}
void build(int u,int l,int r)
{
tag[u]=-1,le[u]=l,ri[u]=r;
if(l==r)
{
sum[u]=mx[u]=w[l],se[u]=-1,cn[u]=1;
}
else
{
int mid=l+r>>1;
build(a,l,mid);
build(b,mid+1,r);
pushup(u);
}
}
void modify_min(int u,int l,int r,int v)
{
if(mx[u]<=v) return ;
if(le[u]>=l&&ri[u]<=r&&se[u]<v)
{
sum[u]+=(ll)(v-mx[u])*cn[u];
tag[u]=mx[u]=v;
return ;
}
pushdown(u);
int mid=le[u]+ri[u]>>1;
if(mid>=l) modify_min(a,l,r,v);
if(mid<r) modify_min(b,l,r,v);
pushup(u);
}
int query_max(int u,int l,int r)
{
if(le[u]>=l&&ri[u]<=r) return mx[u];
pushdown(u);
int mid=le[u]+ri[u]>>1;
int ma=-1;
if(mid>=l) ma=max(ma,query_max(a,l,r));
if(mid<r) ma=max(ma,query_max(b,l,r));
return ma;
}
ll query_sum(int u,int l,int r)
{
if(le[u]>=l&&ri[u]<=r) return sum[u];
pushdown(u);
int mid=le[u]+ri[u]>>1;
ll su=0;
if(mid>=l) su+=query_sum(a,l,r);
if(mid<r) su+=query_sum(b,l,r);
return su;
}
int main()
{
t=read();
while(t--)
{
n=read(),m=read();
for(int i=1;i<=n;i++)
w[i]=read();
build(1,1,n);
while(m--)
{
int op,x,y,z;
op=read(),x=read(),y=read();
if(op==0)
{
z=read();
modify_min(1,x,y,z);
}
else if(op==1)
printf("%d\n",query_max(1,x,y));
else printf("%lld\n",query_sum(1,x,y));
}
}
return 0;
}