#线段树,Beats#CF855F Nagini
分析
先不考虑正负数都要存在,那么相当于正值维护区间最小值,负值维护区间最大值(取反复用)。
将各自区间和加起来,问题是权值和只有正负值同时存在的时候才计算。
由于一方答案不超过 \(10^5\times 10^9<2^{50}\),因此将区间和变成区间和对 \(2^{50}\) 取模。
额外维护两棵线段树操作相同,只是正值维护时将负值的对应区间对 \(0\) 取最小值,反之亦然。
这样如果是 inf 的话另一方正负值的线段树的答案相减就会被抵消掉,而我方取模还是消掉了。
用四棵线段树维护区间最值 Beats 就可以了。
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100011;
typedef long long lll;
const lll inf=(1ll<<50)-1;
struct Segment_Tree{
lll mx[N<<2],semx[N<<2],w[N<<2];
int cntmx[N<<2];
void pup(int k){
w[k]=(w[k<<1]+w[k<<1|1])&inf;
if (mx[k<<1]==mx[k<<1|1])
mx[k]=mx[k<<1],semx[k]=max(semx[k<<1],semx[k<<1|1]),cntmx[k]=cntmx[k<<1]+cntmx[k<<1|1];
else if (mx[k<<1]>mx[k<<1|1])
mx[k]=mx[k<<1],semx[k]=max(semx[k<<1],mx[k<<1|1]),cntmx[k]=cntmx[k<<1];
else mx[k]=mx[k<<1|1],semx[k]=max(mx[k<<1],semx[k<<1|1]),cntmx[k]=cntmx[k<<1|1];
}
void ptag_max(int k,lll z){
if (z>=mx[k]) return;
lll t=(z&inf)-(mx[k]&inf);
w[k]=(w[k]+t*cntmx[k]+inf+1)&inf;
mx[k]=z;
}
void pdown(int k){
if (mx[k<<1]>mx[k]) ptag_max(k<<1,mx[k]);
if (mx[k<<1|1]>mx[k]) ptag_max(k<<1|1,mx[k]);
}
void build(int k,int l,int r){
if (l==r){
w[k]=0,mx[k]=inf+1,semx[k]=-inf-1,cntmx[k]=1;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pup(k);
}
void update(int k,int l,int r,int x,int y,lll z){
if (z>=mx[k]) return;
if (l==x&&r==y&&z>semx[k]){
ptag_max(k,z);
return;
}
int mid=(l+r)>>1;
pdown(k);
if (y<=mid) update(k<<1,l,mid,x,y,z);
else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
pup(k);
}
lll query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return w[k];
int mid=(l+r)>>1;
pdown(k);
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return (query(k<<1,l,mid,x,mid)+query(k<<1|1,mid+1,r,mid+1,y))&inf;
}
}Tre[4];
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int q,n=100000; cin>>q;
for (int i=0;i<4;++i) Tre[i].build(1,1,n);
for (;q;--q){
int opt,l,r; cin>>opt>>l>>r; --r;
if (opt==1){
lll k; cin>>k;
if (k>0){
Tre[0].update(1,1,n,l,r,k);
Tre[1].update(1,1,n,l,r,k);
Tre[3].update(1,1,n,l,r,0);
}
else{
k=-k;
Tre[2].update(1,1,n,l,r,k);
Tre[3].update(1,1,n,l,r,k);
Tre[1].update(1,1,n,l,r,0);
}
}
else{
lll ans=Tre[0].query(1,1,n,l,r)+Tre[2].query(1,1,n,l,r)-Tre[1].query(1,1,n,l,r)-Tre[3].query(1,1,n,l,r);
cout<<((ans+2*(inf+1))&inf)<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号