UOJ #169. 【UR #11】元旦老人与数列 segment-tree-beats

这道题好麻烦的.   

把次小值和最小值一起更新,WA 了半天.           

这道题采用的是势能分析的做法,并没有用到 CPU 监控那道题中的打标记法. 

有时间再研究一下这几类线段树的异同. 

code:   

#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <cmath>     
#define ll long long 
#define N 500006     
#define lson x<<1
#define rson x<<1|1   
#define inf 0x3f3f3f3f     
#define I(s) freopen(s".in","r",stdin) 
#define O(s) freopen(s".out","w",stdout) 
#define setIO(s) I(s),O(s)  
using namespace std; 
int nmin[N<<2],pmin[N<<2],se[N<<2];   
int ptag_a[N<<2],ntag_a[N<<2],ptag_b[N<<2],ntag_b[N<<2];                    
void pushup(int x) 
{
    nmin[x]=min(nmin[lson],nmin[rson]);   
    pmin[x]=min(pmin[lson],pmin[rson]);      
    if(nmin[lson]<nmin[rson])  se[x]=min(se[lson],nmin[rson]);   
    if(nmin[rson]<nmin[lson])  se[x]=min(se[rson],nmin[lson]);  
    if(nmin[lson]==nmin[rson]) se[x]=min(se[lson],se[rson]);   
}   
// v1 表示历史最小                
void mark_a(int x,int v1,int v2) 
{               
    pmin[x]=min(pmin[x],nmin[x]+v1);        
    ptag_a[x]=min(ptag_a[x],ntag_a[x]+v1);     
    nmin[x]+=v2,ntag_a[x]+=v2;                       
} 
void mark_b(int x,int v1,int v2) 
{
    ptag_b[x]=min(ptag_b[x],ntag_b[x]+v1);   
    ntag_b[x]+=v2;    
    if(se[x]!=inf) se[x]+=v2; 
}
void pushdown(int x) 
{     
    int c=min(nmin[lson],nmin[rson]);     
    if(nmin[lson]==c) 
    {
        mark_a(lson,ptag_a[x],ntag_a[x]);       
        mark_b(lson,ptag_b[x],ntag_b[x]);  
    }   
    else 
    {
        mark_a(lson,ptag_b[x],ntag_b[x]);      
        mark_b(lson,ptag_b[x],ntag_b[x]);   
    }    
    if(nmin[rson]==c) 
    {
        mark_a(rson,ptag_a[x],ntag_a[x]);       
        mark_b(rson,ptag_b[x],ntag_b[x]);  
    }   
    else 
    {
        mark_a(rson,ptag_b[x],ntag_b[x]);      
        mark_b(rson,ptag_b[x],ntag_b[x]);   
    }            
    ptag_a[x]=ntag_a[x]=ptag_b[x]=ntag_b[x]=0;    
}                 
void addv(int l,int r,int x,int L,int R,int v) 
{
    if(l>=L&&r<=R) 
    {
        mark_a(x,v,v),mark_b(x,v,v);   
        return; 
    } 
    pushdown(x); 
    int mid=(l+r)>>1;      
    if(L<=mid)  addv(l,mid,lson,L,R,v); 
    if(R>mid)   addv(mid+1,r,rson,L,R,v);     
    pushup(x); 
}
void getmax(int l,int r,int x,int L,int R,int v) 
{   
    if(nmin[x]>=v)  return;   
    if(l>=L&&r<=R&&se[x]>v)  
    {   
        mark_a(x,v-nmin[x],v-nmin[x]);       
        return; 
    } 
    pushdown(x); 
    int mid=(l+r)>>1;  
    if(L<=mid)    getmax(l,mid,lson,L,R,v); 
    if(R>mid)     getmax(mid+1,r,rson,L,R,v);     
    pushup(x); 
}
int queryn(int l,int r,int x,int L,int R) 
{
    if(l>=L&&r<=R) return nmin[x];    
    pushdown(x); 
    int mid=(l+r)>>1;    
    if(L<=mid&&R>mid) return min(queryn(l,mid,lson,L,R),queryn(mid+1,r,rson,L,R));  
    else if(L<=mid) return queryn(l,mid,lson,L,R);  
    else return queryn(mid+1,r,rson,L,R);    
} 
int queryp(int l,int r,int x,int L,int R) 
{
    if(l>=L&&r<=R) return pmin[x];    
    pushdown(x); 
    int mid=(l+r)>>1;    
    if(L<=mid&&R>mid) return min(queryp(l,mid,lson,L,R),queryp(mid+1,r,rson,L,R));  
    else if(L<=mid) return queryp(l,mid,lson,L,R);  
    else return queryp(mid+1,r,rson,L,R);    
} 
void build(int l,int r,int x) 
{
    if(l==r) 
    {
        scanf("%d",&nmin[x]),pmin[x]=nmin[x],se[x]=inf; 
        return;    
    }   
    int mid=(l+r)>>1;    
    build(l,mid,lson),build(mid+1,r,rson);   
    pushup(x);  
}
int main() 
{ 
    // setIO("input"); 
    int n,m;   
    scanf("%d%d",&n,&m),build(1,n,1);  
    for(int i=1;i<=m;++i) 
    {
        int op,l,r,z;  
        scanf("%d%d%d",&op,&l,&r); 
        if(op==1)  scanf("%d",&z),addv(1,n,1,l,r,z);   
        if(op==2)  scanf("%d",&z),getmax(1,n,1,l,r,z);   
        if(op==3)  printf("%d\n",queryn(1,n,1,l,r)); 
        if(op==4)  printf("%d\n",queryp(1,n,1,l,r));    
    }        
    return 0;
}

  

posted @ 2020-03-25 01:24  EM-LGH  阅读(161)  评论(0编辑  收藏  举报