http://acm.hdu.edu.cn/showproblem.php?pid=5306
题意:对于数组 a,三种操作
0 x y t,将区间[x,y]内所有大于t的数换成t
1 x y:输出区间[x,y]内最大值
2 x y:输出区间[x,y]内的所有数的和
思路:这个题很容易固定思维,理解错题意,理解成区间更新成所有数的最小值,,本人一开始也理解错了。。上一次做这个题,因为后期看题解发现读错题。就直接看了一下思路,交了题解,就直接往下进行了,这次就是自己又敲了一遍,因为听其他人说挺烦的,,感觉还可以,就是得想明白了,细节有点多,。
建线段树,每个区间记录区间最大,区间次大值,区间最大值数量,区间和。
每次更新的时候要继续实现这四个记录值的更新完全。满满的做,得注意力十分集中才行,因为细节真的多QAQ
查找什么的就很普通了,跟普通的区间更新一样,要记得维护左右下区间的值。
代码:
#include<bits/stdc++.h>
using namespace std;
long long p,n,m,x,y,t,a[1000005];
struct AA
{
long long maxx,maxn,sum,num;
}pos[4000020];
void build(int rt,int l,int r)
{
if(l==r) {pos[rt].maxx=a[l];pos[rt].maxn=-1;pos[rt].num=1;pos[rt].sum=a[l];return;}
int mid=(l+r)/2;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pos[rt].maxx=max(pos[rt<<1].maxx,pos[rt<<1|1].maxx);
pos[rt].sum=pos[rt<<1].sum+pos[rt<<1|1].sum;
if(pos[rt<<1].maxx==pos[rt<<1|1].maxx)
{pos[rt].num=pos[rt<<1].num+pos[rt<<1|1].num;
pos[rt].maxn=max(pos[rt<<1].maxn,pos[rt<<1|1].maxn);}
else
{pos[rt].maxn=max(max(pos[rt<<1].maxn,pos[rt<<1|1].maxn),min(pos[rt<<1].maxx,pos[rt<<1|1].maxx));
pos[rt].num=pos[rt<<1].maxx>pos[rt<<1|1].maxx?pos[rt<<1].num:pos[rt<<1|1].num;}
return;
}
void BB(int rt,long long ma)
{
if(ma>=pos[rt].maxx) return;
pos[rt].sum-=pos[rt].num*(pos[rt].maxx-ma);
pos[rt].maxx=ma;
}
void pushdown(int rt)
{
BB(rt<<1,pos[rt].maxx);
BB(rt<<1|1,pos[rt].maxx);
}
void change(int rt,int l,int r,int L,int R,long long z)
{
if(pos[rt].maxx<=z) return;
if(L<=l&&r<=R&&pos[rt].maxn<z) {
BB(rt,z);
return;}
int mid=(l+r)/2;
pushdown(rt);
if(R<=mid) change(rt<<1,l,mid,L,R,z);
else if(L>mid) change(rt<<1|1,mid+1,r,L,R,z);
else {
change(rt<<1,l,mid,L,R,z);
change(rt<<1|1,mid+1,r,L,R,z);
}
pos[rt].maxx=max(pos[rt<<1].maxx,pos[rt<<1|1].maxx);
pos[rt].sum=pos[rt<<1].sum+pos[rt<<1|1].sum;
if(pos[rt<<1].maxx==pos[rt<<1|1].maxx)
{pos[rt].num=pos[rt<<1].num+pos[rt<<1|1].num;
pos[rt].maxn=max(pos[rt<<1].maxn,pos[rt<<1|1].maxn);}
else
{pos[rt].maxn=max(max(pos[rt<<1].maxn,pos[rt<<1|1].maxn),min(pos[rt<<1].maxx,pos[rt<<1|1].maxx));
pos[rt].num=pos[rt<<1].maxx>pos[rt<<1|1].maxx?pos[rt<<1].num:pos[rt<<1|1].num;}
return;
}
long long query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return pos[rt].maxx;
}
pushdown(rt);
int mid=(l+r)/2;
if(R<=mid) return query(rt<<1,l,mid,L,R);
else if(L>mid) return query(rt<<1|1,mid+1,r,L,R);
else return max(query(rt<<1,l,mid,L,R),query(rt<<1|1,mid+1,r,L,R));
}
long long querysum(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return pos[rt].sum;
}
pushdown(rt);
int mid=(l+r)/2;
if(R<=mid) return querysum(rt<<1,l,mid,L,R);
else if(L>mid) return querysum(rt<<1|1,mid+1,r,L,R);
else return querysum(rt<<1,l,mid,L,R)+querysum(rt<<1|1,mid+1,r,L,R);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
scanf("%lld%lld%lld",&p,&x,&y);
if(p==0)
{
scanf("%lld",&t);
change(1,1,n,x,y,t);
}
else if(p==1)
{
printf("%lld\n",query(1,1,n,x,y));
}
else if(p==2)
{
printf("%lld\n",querysum(1,1,n,x,y));
}
}
}
}