zkw 递推 线段树二分
Problem
给定序列
问修改前后,有几个区间
询问的更改操作是持久化的。
对于所有的数据,满足
做法
找到最大的满足条件的区间
可以发现该区间的所有包含位置
所以答案就是
线段树二分即可做到
在网上我没找到 zkw 线段树二分,所以自己按照树状数组的思想自己推了下式子:
#include<bits/stdc++.h>
int a[1000005<<2],N,n,m;
int&mx(int&x,int v){return (v>x?x=v:x);}
void C(int x,int k){a[x+=N]=k;while(x>>=1)mx(a[x]=a[x<<1],a[x<<1|1]);}
int B(int x,int v,bool f){
x=N+x;while(a[x]<v){x+=f,x/=(x&-x),x-=!f;if(x==f)return N*f;}
while(x<=N)x=x<<1|f^(a[x<<1|!f]>=v);return x-N;
}int main(){
std::ios::sync_with_stdio(0);std::cin.tie(0),std::cout.tie(0);
std::cin>>n>>m;N=1<<(std::__lg(n)+1);
for(int i=N+1;i<=N+n;++i)std::cin>>a[i];
for(int i=N-1;i>=1;--i)mx(a[i]=a[i<<1],a[i<<1|1]);
while(m--){
int x,y,l,r,v;std::cin>>x>>y>>l>>r;
if(a[N+x]==y){std::cout<<"0\n";continue;}
mx(v=y,a[N+x]),C(x,y);
mx(l,B(x-1,v,0)+1),r=std::min(r,B(x+1,v,1)-1);
std::cout<<int64_t(x-l+1)*(r-x+1)<<"\n";
}return 0;
}
时间(同一个输入输出):