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
我们对于线段树的每个结点,维护最大值max,最大值出现次数cnt,严格次大值sec和区间和sum。
修改时,对于可修改结点k,若
t≥max(k):修改对于该区间无效,返回。
sec(k) < t < max(k):t只对max(k)发生影响,令max(k)=t并更新区间和,返回。
sec(k) ≤ t:无法简单地更新区间和了……
复杂度是 (mlog n),证明的话可以参看16年集训队吉爷的论文
这个题要优化输入输出,否则可能超时
原题链接
#include
#include
#include
#define MAX_N 1000005
using namespace std;
typedef long long LL;
const int MAXS = 40*1024*1024;
char buf[MAXS],bufout[MAXS],*ch,*chout;
void read(int &x){
for(++ch;*ch<=32;++ch);
for(x=0;*ch>='0';++ch) x=x*10+*ch-'0';
}
void out(int x){
if(!x) *(++chout)='0';
else{
char *ch0=chout,*ch1=chout+1;
while(x){
*(++ch0)=x%10+'0';
x/=10;
}
chout=ch0;
while(ch1<=ch0) swap(*(ch1++),*(ch0--));
}
*(++chout)='\n';
}
void out(long long x){
if(!x) *(++chout)='0';
else{
char *ch0=chout,*ch1=chout+1;
while(x){
*(++ch0)=x%10+'0';
x/=10;
}
chout=ch0;
while(ch1<=ch0) swap(*(ch1++),*(ch0--));
}
*(++chout)='\n';
}
void std_init(){
ch=buf-1;
chout=bufout-1;
fread(buf,1,MAXS,stdin);
}
void std_out(){
fwrite(bufout,1,chout-bufout+1,stdout);
}
/*---------------------------------------------------------------*/
struct node{LL sum;int _max,sa,cum;};//和 最大值 次大值 最大值数量
node dat[MAX_N*2+100];
int res[MAX_N];
void maintain(int k){
int tmpk=k<<1;
dat[k].sum=dat[tmpk].sum+dat[tmpk|1].sum;
dat[k].sa=max(dat[tmpk].sa,dat[tmpk|1].sa);
if(dat[tmpk]._max>dat[tmpk|1]._max){
dat[k]._max=dat[tmpk]._max;
dat[k].cum=dat[tmpk].cum;
if(dat[tmpk|1]._max>dat[k].sa) dat[k].sa=dat[tmpk|1]._max;
}else if(dat[tmpk]._max1]._max){
dat[k]._max=dat[tmpk|1]._max;
dat[k].cum=dat[tmpk|1].cum;
if(dat[tmpk]._max>dat[k].sa) dat[k].sa=dat[tmpk]._max;
}else{
dat[k]._max=dat[tmpk]._max;
dat[k].cum=dat[tmpk].cum+dat[tmpk|1].cum;
}
}
void dec(int k,int t){
if(t>=dat[k]._max) return ;
dat[k].sum-=1LL*(dat[k]._max-t)*dat[k].cum;
dat[k]._max=t;
}
void pushdown(int k){
dec(k<<1,dat[k]._max);
dec(k<<1|1,dat[k]._max);
}
void build(int k,int l,int r){
if(l==r) dat[k].sum=dat[k]._max=res[l],dat[k].cum=1,dat[k].sa=-1;
else{
int mid=r+l>>1,tmpk=2*k;
build(tmpk,l,mid);
build(tmpk+1,mid+1,r);
maintain(k);
}
}
void change(int k,int l,int r,int ql,int qr,int t){
if(l>qr||rreturn ;
if(r<=qr&&l>=ql&&t>dat[k].sa){
dec(k,t); return ;
}
pushdown(k);
int mid=r+l>>1,tmpk=2*k;
change(tmpk,l,mid,ql,qr,t);
change(tmpk+1,mid+1,r,ql,qr,t);
maintain(k);
}
int query1(int k,int l,int r,int ql,int qr){
if(l>qr||rreturn 0;
if(r<=qr&&l>=ql) return dat[k]._max;
pushdown(k);
int mid=l+r>>1,tmpk=2*k;
return max(query1(tmpk,l,mid,ql,qr),query1(tmpk+1,mid+1,r,ql,qr));
}
LL query2(int k,int l,int r,int ql,int qr){
if(l>qr||rreturn 0;
if(r<=qr&&l>=ql) return dat[k].sum;
pushdown(k);
int mid=l+r>>1,tmpk=2*k;
return query2(tmpk,l,mid,ql,qr)+query2(tmpk+1,mid+1,r,ql,qr);
}
int main()
{
std_init();
int T;
read(T);
for(int t=1;t<=T;t++){
int n,m;
read(n);read(m);
for(int i=1;i<=n;i++)
read(res[i]);
build(1,1,n);
while(m--){
int op,x,y;
read(op);read(x);read(y);
if(op) out(op==1?query1(1,1,n,x,y):query2(1,1,n,x,y));
else{
int val;read(val);
change(1,1,n,x,y,val);
}
}
}
std_out();
return 0;
}