https://www.lydsy.com/JudgeOnline/problem.php?id=4355
第二问要取最大值不好处理 一开始想的是只有当前区间所有数都一样时才进行加操作 WA...应该是T啊...
看了正解 感觉时间复杂度很玄学 首先根据题意发现 如果区间内有零存在 那一定是以最小值的形式存在 所以要记录最小值及其数量 通过维护区间最小和次小值来剪枝
具体看这篇博客https://blog.csdn.net/clover_hxy/article/details/72977782
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f
struct node
{
int l;
int r;
int cnt;
ll minn;
ll cminn;
ll laz1;
ll laz2;
ll laz3;
};
node tree[1200010];
int n,q;
void pushup(int cur)
{
tree[cur].minn=min(tree[2*cur].minn,tree[2*cur+1].minn);
tree[cur].cnt=0;
if(tree[cur].minn==tree[2*cur].minn) tree[cur].cnt+=tree[2*cur].cnt;
if(tree[cur].minn==tree[2*cur+1].minn) tree[cur].cnt+=tree[2*cur+1].cnt;
tree[cur].cminn=N;
if(tree[cur].minn!=tree[2*cur].minn) tree[cur].cminn=min(tree[cur].cminn,tree[2*cur].minn);
if(tree[cur].minn!=tree[2*cur+1].minn) tree[cur].cminn=min(tree[cur].cminn,tree[2*cur+1].minn);
tree[cur].cminn=min(tree[cur].cminn,tree[2*cur].cminn);
tree[cur].cminn=min(tree[cur].cminn,tree[2*cur+1].cminn);
}
void pushdown(int cur)
{
ll val;
val=tree[cur].laz1;
if(val!=N)
{
tree[2*cur].cnt=tree[2*cur].r-tree[2*cur].l+1;
tree[2*cur].minn=val;
tree[2*cur].cminn=N;
tree[2*cur].laz1=val;
tree[2*cur].laz2=0;
tree[2*cur].laz3=-N;
tree[2*cur+1].cnt=tree[2*cur+1].r-tree[2*cur+1].l+1;
tree[2*cur+1].minn=val;
tree[2*cur+1].cminn=N;
tree[2*cur+1].laz1=val;
tree[2*cur+1].laz2=0;
tree[2*cur+1].laz3=-N;
tree[cur].laz1=N;
}
val=tree[cur].laz2;
if(val!=0)
{
tree[2*cur].minn+=val;
if(tree[2*cur].cminn!=N) tree[2*cur].cminn+=val;
tree[2*cur].laz2+=val;
if(tree[2*cur].laz3!=-N) tree[2*cur].laz3+=val;
tree[2*cur+1].minn+=val;
if(tree[2*cur+1].cminn!=N) tree[2*cur+1].cminn+=val;
tree[2*cur+1].laz2+=val;
if(tree[2*cur+1].laz3!=-N) tree[2*cur+1].laz3+=val;
tree[cur].laz2=0;
}
val=tree[cur].laz3;
if(val!=-N)
{
tree[2*cur].minn=max(tree[2*cur].minn,val);
tree[2*cur].laz3=max(tree[2*cur].laz3,val);
tree[2*cur+1].minn=max(tree[2*cur+1].minn,val);
tree[2*cur+1].laz3=max(tree[2*cur+1].laz3,val);
tree[cur].laz3=-N;
}
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].cnt=0;
tree[cur].minn=N;
tree[cur].cminn=N;
tree[cur].laz1=N;
tree[cur].laz2=0;
tree[cur].laz3=-N;
if(l==r)
{
scanf("%lld",&tree[cur].minn);
tree[cur].cnt=1;
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
}
void updateI(int pl,int pr,ll val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].cnt=tree[cur].r-tree[cur].l+1;
tree[cur].minn=val;
tree[cur].cminn=N;
tree[cur].laz1=val;
tree[cur].laz2=0;
tree[cur].laz3=-N;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) updateI(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) updateI(pl,pr,val,2*cur+1);
pushup(cur);
}
void updateII(int pl,int pr,ll val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].minn+=val;
if(tree[cur].cminn!=N) tree[cur].cminn+=val;
tree[cur].laz2+=val;
if(tree[cur].laz3!=-N) tree[cur].laz3+=val;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) updateII(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) updateII(pl,pr,val,2*cur+1);
pushup(cur);
}
void updateIII(int pl,int pr,ll val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
if(tree[cur].minn>=val) return;
if(tree[cur].cminn>val)
{
tree[cur].minn=val;
tree[cur].laz3=val;
return;
}
}
if(tree[cur].l==tree[cur].r) return;
pushdown(cur);
if(pl<=tree[2*cur].r) updateIII(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) updateIII(pl,pr,val,2*cur+1);
pushup(cur);
}
int query(int pl,int pr,int cur)
{
int res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
if(tree[cur].minn==0) return tree[cur].cnt;
else return 0;
}
pushdown(cur);
res=0;
if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}
int main()
{
ll val;
int i,op,l,r;
while(scanf("%d%d",&n,&q)!=EOF)
{
build(1,n,1);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld",&l,&r,&val);
updateI(l,r,val,1);
}
else if(op==2)
{
scanf("%d%d%lld",&l,&r,&val);
updateII(l,r,val,1);
updateIII(l,r,0,1);
}
else
{
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r,1));
}
}
}
return 0;
}