• CF997E Good Subsegments


    题目

    分析

    析合树模板题的加强,变成了每次区间询问。

    考虑容斥,也就是我们这里只要算中间被完全包含的那一段区间的所有子树和左右边界的右左的一部分。

    具体见题解。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template<typename T>
    inline void read(T&x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template<typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    #define int long long
    #define PII pair<int,int>
    #define mp make_pair
    const int N=5e5+5;
    int n,m,a[N];
    namespace RMQ1{
    	int Max[21][N],lg[N];
    	inline void Init(int n){
    		for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
    		for(int i=1;i<=n;i++) Max[0][i]=a[i];
    		for(int i=1;i<=20;i++) for(int j=1;j+(1<<i)-1<=n;j++) Max[i][j]=max(Max[i-1][j],Max[i-1][j+(1<<(i-1))]);
    		return ;
    	}
    	inline int Query(int l,int r){
    		int tmp=lg[r-l+1];
    		return max(Max[tmp][l],Max[tmp][r-(1<<tmp)+1]);
    	}
    }
    namespace RMQ2{
    	int Min[21][N],lg[N];
    	inline void Init(int n){
    		for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
    		for(int i=1;i<=n;i++) Min[0][i]=a[i];
    		for(int i=1;i<=20;i++) for(int j=1;j+(1<<i)-1<=n;j++) Min[i][j]=min(Min[i-1][j],Min[i-1][j+(1<<(i-1))]);
    		return ;
    	}
    	inline int Query(int l,int r){
    		int tmp=lg[r-l+1];
    		return min(Min[tmp][l],Min[tmp][r-(1<<tmp)+1]);
    	}
    }
    int Min[N<<2],ad[N<<2];
    inline void Pushup(int x){Min[x]=min(Min[x<<1],Min[x<<1|1]);return ;}
    inline void PushDown(int x){
    	if(!ad[x]) return ;
    	ad[x<<1]+=ad[x],ad[x<<1|1]+=ad[x];
    	Min[x<<1]+=ad[x],Min[x<<1|1]+=ad[x];ad[x]=0;
    	return ;
    }
    void Modify(int x,int l,int r,int ql,int qr,int v){
    	if(ql<=l&&r<=qr) return Min[x]+=v,ad[x]+=v,void();
    	PushDown(x);int mid=l+r>>1;
    	if(ql<=mid) Modify(x<<1,l,mid,ql,qr,v);
    	if(qr>mid) Modify(x<<1|1,mid+1,r,ql,qr,v);
    	Pushup(x);
    	return;
    }
    int Query(int x,int l,int r){
    	if(l==r) return l;
    	PushDown(x);int mid=l+r>>1;
    	if(!Min[x<<1]) return Query(x<<1,l,mid);
    	return Query(x<<1|1,mid+1,r);
    }
    inline bool Check(int l,int r){return RMQ1::Query(l,r)-RMQ2::Query(l,r)==r-l;}
    int head[N],nex[N<<1],to[N<<1],idx;
    vector<int>vec[N];
    inline void add(int u,int v){
    	vec[u].push_back(v);
    	return ;
    }
    int fa[N][21],dep[N];
    #define ll long long
    ll sum[N],pre[N],suf[N],pos[N],val[N],Sum[N];
    int rt,top1,top2,sta1[N],sta2[N],id[N],L[N],R[N],top,sta[N],cnt,typ[N],lc[N];
    inline bool cmp(int x,int y){return L[x]<L[y];}
    void dfs(int u,int f){
    	fa[u][0]=f,dep[u]=dep[f]+1;
    	Sum[u]=typ[u]?((int)vec[u].size()*((int)vec[u].size()-1)/2):(1);
    	
    	for(int i=1;i<=19;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    	int tmp=0;
    	for(int i=0;i<vec[u].size();i++){
    		int v=vec[u][i];
    		dfs(v,u),Sum[u]+=Sum[v],pre[v]=tmp+(typ[u]?(i*(i-1)/2):0),tmp+=Sum[v],sum[v]=tmp,pos[v]=i+1;
    	}
    	tmp=0;
    	for(int i=(int)vec[u].size()-1;i>=0;i--) { 
    		int v=vec[u][i];suf[v]=tmp+(typ[u]?(((int)vec[u].size()-1-i)*((int)vec[u].size()-1-i-1)/2):0),tmp+=Sum[v];
    	}
    }
    void dfs1(int x,int f){
    	suf[x]+=suf[f],pre[x]+=pre[f];
    	for(auto y:vec[x]) dfs1(y,x);
    	return ;
    }
    inline int QueryKth(int u,int k){
    	for(int i=0;i<=20&&k;i++) if(k&(1<<i)) u=fa[u][i],k-=(1<<i);
    	return u;
    }
    inline int QueryLca(int u,int v){
    	if(dep[u]<dep[v]) swap(u,v);
    	u=QueryKth(u,dep[u]-dep[v]);
    	if(u==v) return u;
    	for(int i=20;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    	return fa[u][0];
    }
    
    void Build(){
    	for(int i=1;i<=n;i++){
    		while(top1&&a[i]<=a[sta1[top1]]) Modify(1,1,n,sta1[top1-1]+1,sta1[top1],a[sta1[top1]]),top1--;
    		while(top2&&a[i]>=a[sta2[top2]]) Modify(1,1,n,sta2[top2-1]+1,sta2[top2],-a[sta2[top2]]),top2--;
    		Modify(1,1,n,sta1[top1]+1,i,-a[i]),sta1[++top1]=i;
    		Modify(1,1,n,sta2[top2]+1,i,a[i]),sta2[++top2]=i;
    		id[i]=++cnt,L[cnt]=R[cnt]=i;
    		int tmp=Query(1,1,n),now=cnt;
    		while(top&&L[sta[top]]>=tmp){
    			if(typ[sta[top]]&&Check(lc[sta[top]],i)) R[sta[top]]=i,lc[sta[top]]=L[now],add(sta[top],now),now=sta[top--];
    			else if(Check(L[sta[top]],i)) typ[++cnt]=1,R[cnt]=i,L[cnt]=L[sta[top]],lc[cnt]=L[now],add(cnt,sta[top--]),add(cnt,now),now=cnt;
    			else{
    				add(++cnt,now);
    				do{add(cnt,sta[top--]);}while(top&&!Check(L[sta[top]],i));
    				R[cnt]=i,L[cnt]=L[sta[top]],add(cnt,sta[top--]),now=cnt;
    			}
    		}
    		sta[++top]=now;
    		Modify(1,1,n,1,i,-1);
    	}
    	rt=sta[1];
    	return ;
    }
    inline ll Query(int l,int r){
    	int Lca=QueryLca(id[l-1],id[r+1]),x=QueryKth(id[l-1],dep[id[l-1]]-dep[Lca]-1),y=QueryKth(id[r+1],dep[id[r+1]]-dep[Lca]-1);
    	int res=suf[id[l-1]]-suf[x]+pre[id[r+1]]-pre[y]+sum[y]-sum[x]-Sum[y];
    	if(typ[Lca]==1) res+=(pos[y]-pos[x]-1)*(pos[y]-pos[x]-2)/2;
    	return res;
    }
    int Querypre(int r) {
    	int x=QueryKth(id[r+1],dep[id[r+1]]-dep[rt]-1);
    	return pre[id[r+1]]-pre[x]+sum[x]-Sum[x]+(typ[rt]?((pos[x]-1)*(pos[x]-2)/2):0);
    }
    
    int Querysuf(int l) {
    	int x=QueryKth(id[l-1],dep[id[l-1]]-dep[rt]-1);
    	return suf[id[l-1]]-suf[x]+sum[(int)vec[rt][vec[rt].size()-1]]-sum[x]+(typ[rt]?((vec[rt].size()-pos[x])*((vec[rt].size()-pos[x])-1)/2):0);
    }
    int Solve(int l,int r){
        if(l==1&&r==n) return Sum[rt];
        else if(l!=1&&r==n) return Querysuf(l);
    	else if(l==1&&r!=n) return Querypre(r);
    	return Query(l, r);
    }
    signed main(){
    	read(n);
    	for(int i=1;i<=n;i++) read(a[i]);
    	RMQ1::Init(n),RMQ2::Init(n);
    	Build();for(int i=1;i<=cnt;i++) sort(vec[i].begin(),vec[i].end(),cmp);
    	dfs(rt,0);dfs1(rt,0);
    	read(m);
    	for(int i=1;i<=m;i++){
    		int l,r;
    		read(l),read(r);
    		write(Solve(l,r)),putchar('
    ');
    	}
    	return 0;
    }
    
    

    总结

  • 相关阅读:
    JavaScript函数中的this四种绑定形式
    jQuery的html()、text()和val()的使用和区别
    iframe-父子-兄弟页面相互传值(jq和js两种方法)
    Spring Boot 嵌入式 Tomcat 文件上传、url 映射虚拟路径
    SpringMVC上传图片
    <iframe>和<frame>标签属性详解
    Mybatis 事物回滚最简单的操作方式
    SpringBoot配置log4j
    springboot整合redis(集群)
    Maven setting.xml简易配置
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14932414.html
Copyright © 2020-2023  润新知