CF1039E Summer Oenothera Exhibition 根号分治+LCT+ST表

好神仙的数据结构题呀! 

code: 

#include <cstdio> 
#include <cstring> 
#include <vector>   
#include <cmath>   
#include <algorithm>   
#define BL 250     
#define N 100006    
#define inf 0x7fffffff
#define setIO(s) freopen(s".in","r",stdin)  
using namespace std;  
int n,arr[N];  
namespace ST 
{    
	int maxv[18][N],minv[18][N],bin[18];    
	inline void init() 
	{
		int i,j;     
		for(i=0;i<18;++i)  bin[i]=(1<<i);          
		for(i=1;i<=n+1;++i)   
			maxv[0][i]=minv[0][i]=arr[i];          
		for(i=1;i<18;++i) 
			for(j=1;j+bin[i]-1<=n+1;++j) 
			{
				maxv[i][j]=max(maxv[i-1][j],maxv[i-1][j+bin[i-1]]);   
				minv[i][j]=min(minv[i-1][j],minv[i-1][j+bin[i-1]]);       
			}    
	}
	inline int q_max(int l,int r) 
	{        
		int p=log2(r-l+1);    
		return max(maxv[p][l],maxv[p][r-bin[p]+1]);   
	}   
	inline int q_min(int l,int r) 
	{  
		int p=log2(r-l+1);   
		return min(minv[p][l],minv[p][r-bin[p]+1]);  
	}    
	inline int query(int l,int r) { return q_max(l,r)-q_min(l,r); }
};    
namespace LCT
{      
    #define lson s[x].ch[0]
    #define rson s[x].ch[1] 
    int sta[N];  
    struct data 
    {  
        int ch[2],rev,f,siz;                
    }s[N];            
    inline int get(int x) { return s[s[x].f].ch[1]==x; } 
    inline int isr(int x) {  return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; }
    inline void pushup(int x) 
    {
    	s[x].siz=s[lson].siz+s[rson].siz+1;     
    }     
    inline void rotate(int x)
    {
        int old=s[x].f,fold=s[old].f,which=get(x); 
        if(!isr(old)) 
        	s[fold].ch[s[fold].ch[1]==old]=x;  
        s[old].ch[which]=s[x].ch[which^1]; 
        if(s[old].ch[which]) 
            s[s[old].ch[which]].f=old; 
        s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; 
        pushup(old),pushup(x);     
    }    
    inline void mark(int x)
    {
        swap(lson,rson);   
        s[x].rev^=1;   
    }
    inline void pushdown(int x)
    {
        if(s[x].rev)
        {
            if(lson) 
            	mark(lson);
            if(rson) 
            	mark(rson);
            s[x].rev=0;  
        }
    }
    inline void splay(int x)
    {
        int u=x,v=0,fa; 
        for(sta[++v]=u;!isr(u);u=s[u].f) 
        	sta[++v]=s[u].f;       
        for(;v;--v) 
        	pushdown(sta[v]);  
        for(u=s[u].f;(fa=s[x].f)!=u;rotate(x)) 
            if(s[fa].f!=u)
                rotate(get(fa)==get(x)?fa:x);  
    }
    inline void Access(int x)
    {
        for(int y=0;x;y=x,x=s[x].f)
            splay(x),rson=y,pushup(x);    
    }        
    inline void link(int x,int y) { s[y].f=x; }      
    // 断掉 y 与父亲     
    inline void cut(int y)
    {    
    	Access(y),splay(y);     
        s[s[y].ch[0]].f=0,s[y].ch[0]=0,pushup(y);  
    }
    inline int frt(int x)  
    {
    	while(lson) 
    		x=lson;    
    	return x;   
    }
    #undef lson
    #undef rson
};   
struct ask 
{   
	int k,id; 
	bool operator<(const ask b) const { return k<b.k; }
}q[N];     
int h[N],mark[N],A[N],Ans[N];    
vector<int>G[N];     
int find(int x,int k) 
{
	int l=x+1,r=n+1,mid;     
	for(mid=(l+r)>>1;l<r;mid=(l+r)>>1)     
	{
		int cu=ST::query(x,mid);     
		if(cu>k)   
			r=mid; 
		else 
			l=mid+1;    
	} 
	return mid;  
}                          
int main() 
{
	// setIO("input"); 
	int i,j,B,W,Q;      
	scanf("%d%d%d",&n,&W,&Q);  
	B=sqrt(n);       
	for(i=1;i<=n;++i)   
		scanf("%d",&arr[i]);  
	arr[n+1]=inf;           
	ST::init();      
	for(i=1;i<=n;++i)  
		LCT::s[i].siz=1;  
	for(i=1;i<=Q;++i)     
	{
		scanf("%d",&q[i].k); 
		A[i]=q[i].k=W-q[i].k,q[i].id=i;  
	}       
	sort(q+1,q+1+Q);       
	for(i=1;i<=n;++i)   
		h[i]=i,LCT::s[i].f=i+1,G[1].push_back(i);           
	for(i=1;i<=Q;++i) 
	{
		int o,t,k;      
		for(o=j=0;j<G[i].size();++j)    
		{
			int u=G[i][j];    
			LCT::cut(u);         
			for(k=h[u]+1;ST::query(u,k)<=q[i].k&&k-u<=B&&k<=n;++k);      
			if(k-u>B)  
				mark[u]=1;   
			else 
			{
				h[u]=k; 
				LCT::s[u].f=h[u]; 
				G[lower_bound(q+1,q+1+Q,(ask){ST::query(u,h[u]),0})-q].push_back(u);  
			} 
		}
		for(j=1;;j=find(j,q[i].k),++o) 
		{
			if(!mark[j])   
			{
				LCT::Access(j);   
				LCT::splay(j);    
				o+=LCT::s[j].siz-1;    
				j=LCT::frt(j);   
			}
			if(j>n)
				break;    
		}
		Ans[q[i].id]=o-1;  
	}
	for(i=1;i<=Q;++i)   
		printf("%d\n",Ans[i]);  
	return 0;  
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/12426958.html