维护线段树,在其每一个节点上维护一个set(可重),以及子树内所有set的最大值
考虑下传标记,如果将所有元素全部下传复杂度显然不正确,但注意到我们仅关心于其中的最大值,即仅需要将最大值下传即可
其有可能需要在已经被完全覆盖的区间内继续递归,以找到”子树内所有set的最大值“的位置
关于这一做法的复杂度,可以均摊为总标记数,注意到前者下传标记至多增加$o(log n)$个,即可得总复杂度为$o(nlog^{2}n)$(每一次操作还有set的$o(log n)$)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 priority_queue<int>S[N<<3]; 8 int n,m,p,x,y,z,f[N<<3]; 9 void up(int k){ 10 if (S[k].empty())f[k]=max(f[L],f[R]); 11 else f[k]=max(max(f[L],f[R]),S[k].top()); 12 } 13 void add(int k,int x){ 14 S[k].push(x); 15 f[k]=max(f[k],x); 16 } 17 void del(int k){ 18 S[k].pop(); 19 up(k); 20 } 21 void down(int k){ 22 if (!S[k].empty()){ 23 add(L,S[k].top()); 24 add(R,S[k].top()); 25 S[k].pop(); 26 } 27 } 28 void add(int k,int l,int r,int x,int y,int z){ 29 if ((l>y)||(x>r))return; 30 if ((x<=l)&&(r<=y)){ 31 add(k,z); 32 return; 33 } 34 add(L,l,mid,x,y,z); 35 add(R,mid+1,r,x,y,z); 36 up(k); 37 } 38 void del(int k,int l,int r,int x,int y,int z){ 39 if ((l>y)||(x>r))return; 40 if ((x<=l)&&(r<=y)){ 41 if (f[k]<z)return; 42 if ((!S[k].empty())&&(S[k].top()==z)){ 43 del(k); 44 return; 45 } 46 } 47 del(L,l,mid,x,y,z); 48 del(R,mid+1,r,x,y,z); 49 up(k); 50 } 51 int query(int k,int l,int r,int x,int y){ 52 if ((l>y)||(x>r))return -1; 53 if ((x<=l)&&(r<=y))return f[k]; 54 down(k); 55 return max(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 56 } 57 int main(){ 58 scanf("%d%d",&n,&m); 59 memset(f,-1,sizeof(f)); 60 for(int i=1;i<=m;i++){ 61 scanf("%d%d%d",&p,&x,&y); 62 if (p==1){ 63 scanf("%d",&z); 64 add(1,1,n,x,y,z); 65 } 66 if (p==2){ 67 z=query(1,1,n,x,y); 68 if (z>=0)del(1,1,n,x,y,z); 69 } 70 if (p==3)printf("%d ",query(1,1,n,x,y)); 71 } 72 }