题意:给定\(a[1...n]\),\(m\)次操作,0表示使\([L,R]\)中的值\(a[i]=min(a[i],x)\),其余的1是查最值2是查区间和

本题是jls的2016论文题,1 2套路不说

对于操作0,维护当前最值和严格次大最值,更新过程分三种情况

1.当前的最大值本来就比\(x\)小或相等,直接剪枝(全局剪枝更优,道理不必多说)

2.当前最大值大于\(x\),次大值小于等于\(x\),那么影响到的值只有最大值,打个tag维护

3.其它情况,暴力dfs

具体地,\(max\)值的改变影响了\(sum\)值,那我们需要维护的tag需要值为\(max\)的个数,此时\(sum\)只需做差相减

论文证明这种操作下依然是\(O(logn)\)的

代码改得比较多,略丑

细节要注意的地方也挺多的

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)a)
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 1e6+11;
const int NN = 1e5+11;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
typedef long long ll;
const ll MOD = 1e9+7;
ll read() {
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int a[MAXN];
struct ST{
#define lc o<<1
#define rc o<<1|1
int mx[MAXN<<2],smx[MAXN<<2],mxcnt[MAXN<<2];
ll sum[MAXN<<2];
bool lazy[MAXN<<2];
void pu(int o){
mx[o]=max(mx[lc],mx[rc]);
sum[o]=sum[lc]+sum[rc];
smx[o]=max(smx[lc],smx[rc]);
mxcnt[o]=0;
if(mx[lc]!=mx[rc]) smx[o]=max(smx[o],min(mx[lc],mx[rc]));//
if(mx[lc]==mx[o]) mxcnt[o]+=mxcnt[lc];
if(mx[rc]==mx[o]) mxcnt[o]+=mxcnt[rc];
}
void pd(int o){
if(lazy[o]){
if(mx[lc]>mx[o]){
lazy[lc]=1;
sum[lc]-=1ll*(mx[lc]-mx[o])*mxcnt[lc];
mx[lc]=mx[o];
}
if(mx[rc]>mx[o]){
lazy[rc]=1;
sum[rc]-=1ll*(mx[rc]-mx[o])*mxcnt[rc];
mx[rc]=mx[o];
}
lazy[o]=0;
// lazy[lc]=lazy[rc]=1;
}
}
void build(int o,int l,int r){
mx[o]=smx[o]=-INF;mxcnt[o]=lazy[o]=sum[o]=0;
if(l==r){
sum[o]=mx[o]=a[l];
// smx[o]=-INF;
mxcnt[o]=1;
return;
}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pu(o);
}
void update(int o,int l,int r,int L,int R,int v){
if(mx[o]<=v) return; // 全局剪枝
if(L<=l&&r<=R){
// if(mx[o]<=v)return;
if(smx[o]<=v){//只改变最大值
// pd(o);
lazy[o]=1;
sum[o]-=1ll*(mx[o]-v)*mxcnt[o];
mx[o]=v;//mxcnt bu bian
return;
}
}
pd(o);
int mid=l+r>>1;
if(L<=mid) update(lc,l,mid,L,R,v);
if(R>mid) update(rc,mid+1,r,L,R,v);
pu(o);
}
ll queryMax(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return mx[o];
pd(o);
int mid=l+r>>1;
ll res=-INF;
if(L<=mid) res=max(res,queryMax(lc,l,mid,L,R));
if(R>mid) res=max(res,queryMax(rc,mid+1,r,L,R));
return res;
}
ll querySum(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[o];
pd(o);
int mid=l+r>>1;
ll res=0;
if(L<=mid) res+=querySum(lc,l,mid,L,R);
if(R>mid) res+=querySum(rc,mid+1,r,L,R);
return res;
}
}st;
int main(){
int T=read();
while(T--){
int n=read();
int m=read();
rep(i,1,n) a[i]=read();
st.build(1,1,n);
rep(i,1,m){
int op=read();
int x=read();
int y=read();
if(op==0){
int t=read();
st.update(1,1,n,x,y,t);
}else if(op==1){
println(st.queryMax(1,1,n,x,y));
}else{
println(st.querySum(1,1,n,x,y));
}
}
}
return 0;
}

最新文章

  1. Java与MySQL的连接
  2. 【HDU2255】奔小康赚大钱-KM算法
  3. git 最基本的使用方法
  4. Css_Backgroud-position(背景图片)定位问题详解
  5. [Js]表格排序
  6. 微软职位内部推荐-Principal Dev Manager
  7. 对JavaScript对象数组按指定属性和排序方向进行排序
  8. 浅谈 qmake 之 shadow build(就是将源码路径和构建路径分开)
  9. 三个创建WebStorm项目的方法
  10. SpringMVC中使用@Value给非String类型注入值
  11. JavaScripy execCommand函数
  12. JS数组添加删除
  13. springboot加ES实现全局检索
  14. 12-tinyMCE文本编辑器+图片上传预览+页面倒计时自动跳转
  15. pl-svo在ROS下运行笔记
  16. 学习Acegi应用到实际项目中(6)
  17. GooglePlay发布应用后,支持的 Android 设备 0 台设备
  18. form提交循环
  19. 高效办公必不可少的5个Excel技巧
  20. 多线程消息监听容器配置[ 消费者spring-kafka配置文件]

热门文章

  1. Python爬虫实战三之实现山东大学无线网络掉线自动重连
  2. Oracle 自增长id
  3. mysql varchar 类型 超出字符
  4. Insufficient free space for journal files
  5. [GO]匿名字段的同名字段操作
  6. php 导出csv表格文件
  7. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试
  8. mybatis--mapper配置总结
  9. SQL存储过程编写,包含临时表
  10. OCP 12c最新考试题库及答案(071-2)