• UOJ#515. 【UR #19】前进四 离线+吉司机线段树


    离线,然后从后向前扫描,维护每一个时刻当前位置的后缀最小值.

    我们发现依次修改影响的是时间线段树一段区间要取 min,这个用吉司机线段树维护就好了.

    具体地,我们记录一个 tag 标记,然后下传条件是 mx[now]<mx[lson] 或 mx[now]<mx[rson].   

    这道题卡常,最好不要用 vector 来存储操作.     

    code: 

    #include <bits/stdc++.h>   
    #define N 2000009  
    #define ll long long 
    #define lson now<<1 
    #define rson now<<1|1  
    #define inf 2000000009    
    #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)  
    using namespace std;     
    int n,m,Q;  
    int mx[N<<2],se[N<<2],tag[N<<2],a[N];   
    void pushup(int now) 
    {
    	mx[now]=max(mx[lson],mx[rson]);   
    	if(mx[lson]==mx[rson]) se[now]=max(se[lson],se[rson]);   
    	else if(mx[lson]<mx[rson]) se[now]=max(mx[lson],se[rson]);  
    	else se[now]=max(mx[rson],se[lson]);  
    }   
    void pushdown(int now) 
    {   
    	if(mx[lson]>mx[now]) mx[lson]=mx[now],tag[lson]+=tag[now];   
    	if(mx[rson]>mx[now]) mx[rson]=mx[now],tag[rson]+=tag[now];  
    	tag[now]=0;  
    }
    void update(int l,int r,int now,int L,int R,int v) 
    {
    	if(mx[now]<=v) return;   
    	if(l>=L&&r<=R&&se[now]<v) 
    	{       
    		mx[now]=v,++tag[now];  
    		return;  
    	}      
    	pushdown(now);   
    	int mid=(l+r)>>1;   
    	if(L<=mid)  update(l,mid,lson,L,R,v);  
    	if(R>mid)   update(mid+1,r,rson,L,R,v);  
    	pushup(now);   
    }   
    int query(int l,int r,int now,int p) 
    {
    	if(l==r) return tag[now];            
    	int mid=(l+r)>>1;    
    	pushdown(now); 
    	if(p<=mid) return query(l,mid,lson,p); 
    	else return query(mid+1,r,rson,p);      
    } 
    void build(int l,int r,int now) 
    {     
    	mx[now]=inf,se[now]=-inf;    
    	if(l==r) return;  
    	int mid=(l+r)>>1;  
    	build(l,mid,lson),build(mid+1,r,rson);  
    }
    int Ans[N];  
    vector<int>q[N]; 
    struct data 
    { 
    	int x,t;  
    	data(int x=0,int t=0):x(x),t(t){}   
    	bool operator<(const data b) const { return t<b.t; }   
    }er[N];
    int hd[N],nex[N],edges;      
    void add(int u,data e) 
    {
    	nex[++edges]=hd[u],hd[u]=edges,er[edges]=e;   
    }           
    char *p1,*p2,buf[100000];    
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)     
    int rd() 
    { 
    	int x=0; char c;  
    	while(c<48) c=nc();   
    	while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();  
    	return x;  
    }    
    int main() 
    { 
    	// setIO("input");     
    	int x,y,z;  
    	n=rd(),m=rd();   
    	for(int i=1;i<=n;++i)  a[i]=rd(),add(i,data(a[i],0));           
    	for(int i=1;i<=m;++i) 
    	{        
    		x=rd();  
    		if(x==1) y=rd(),z=rd(),add(y,data(z,i));    // z 时刻开始生效         
    		if(x==2) y=rd(),q[y].push_back(i);   
    	}         
    	build(0,m,1);           
    	for(int i=n;i>=1;--i) 
    	{   
    		int pr=m;  
    		for(int j=hd[i];j;j=nex[j]) 
    		{    
    			data e=er[j];   
    			int r=pr,l=e.t;              
    			update(0,m,1,l,r,e.x);           
    			pr=e.t-1;  
    		}
    		for(int j=0;j<q[i].size();++j)  Ans[q[i][j]]=query(0,m,1,q[i][j]);   
    	}          
    	for(int i=1;i<=m;++i) if(Ans[i]) printf("%d
    ",Ans[i]);  
    	return 0; 
    }
    

      

  • 相关阅读:
    Android -- junit测试框架,logcat获取log信息
    【Android】ADB常用指令与logcat日志
    Android -- UI布局管理,相对布局,线性布局,表格布局,绝对布局,帧布局
    Unicode的解救方案
    第一个程序
    Windows程序设计第五版
    愉快的开始
    图形用户界面入门:EasyGui
    丰富的else语句及简洁的with语句
    异常处理:你不可能总是对的2
  • 原文地址:https://www.cnblogs.com/guangheli/p/13066328.html
Copyright © 2020-2023  润新知