zoukankan      html  css  js  c++  java
  • 题解[LuoguP4755 Beautiful Pair]

    题目

    Luogu

    Sol

    提供一个可能不那么正常的想法。

    tags:笛卡尔树+分治

    先根据原序列建一棵笛卡尔树出来,以位置为第一关键值(满足二叉查找树性质),权值为第二关键字(满足大根堆性质)。

    对于一个区间([l,r]):

    我们先找到区间中的最大值,设它的位置为(pos)

    我们现在只考虑([pos+1,r])([l,pos-1])的贡献,也就是跨过了最大值的贡献。

    我们把([l,pos-1])从大到小排序,([pos+1,r])从小到大排序。

    由于左区间递减,所以(frac{a_{l_1}}{a_{pos}})递增,满足单调性。

    可以用两个指针(l_1,l_2)分别在最大值左边和右边的区间移动,每次把右边区间小于等于(frac{a_{l_1}}{a_{pos}})的数计入答案。

    (这里带了一点(CDQ)的思想)

    记得最后要还原区间,不然往下递归时会出错。

    那最大值(pos)的贡献怎么算?

    很简单,统计整个区间一的个数就可以了。

    Code

    还挺短的

    #include<bits/stdc++.h>
    #define N (100010)
    #define ll long long
    using namespace std;
    struct xbk{int id;ll v;}a[N];
    int n,rt,ls[N],rs[N];
    ll ans,sum[N];
    vector<int>v;
    inline ll read(){
    	ll w=0;
    	char ch=getchar();
    	while(ch>'9'||ch<'0') ch=getchar();
    	while(ch>='0'&&ch<='9'){
    		w=(w<<3)+(w<<1)+(ch^48);
    		ch=getchar();
    	}
    	return w;	
    }
    inline bool cmp1(xbk a,xbk b){return a.id<b.id;}
    inline bool cmp2(xbk a,xbk b){return a.v<b.v;}
    inline bool cmp3(xbk a,xbk b){return a.v>b.v;}
    inline void build(){
    	for(int i=1;i<=n;i++){
    		int j=0;
    		while(v.size()&&a[v.back()].v<a[i].v) j=v.back(),v.pop_back();
    		if(!v.size()) rt=i;
    		else rs[v.back()]=i;
    		ls[i]=j;
    		v.push_back(i);
    	}
    	return;
    }
    inline void binary(int st,int l,int r){
    	int ll1=st-1,rr1=st+1,flag=0;
    	ans+=sum[r]-sum[l-1];
    	if(ll1>=l&&r>=rr1){
    		flag=1;
    		sort(a+l,a+ll1+1,cmp3),sort(a+rr1,a+r+1,cmp2);
    		for(int l1=l,l2=rr1;l1<=ll1;l1++){
    			ll val=a[st].v/a[l1].v;
    			while(a[l2].v<=val&&l2<=r) l2++;
    			ans+=l2-rr1;
    		}
    	}
    	if(flag) sort(a+l,a+r+1,cmp1);
    	if(ls[st]) binary(ls[st],l,st-1);
    	if(rs[st]) binary(rs[st],st+1,r);
    	return;
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		a[i].v=read(),a[i].id=i;
    	    sum[i]=sum[i-1]+(a[i].v==1);
    	}
    	build();
    	binary(rt,1,n);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    完结撒花❀

  • 相关阅读:
    原码, 反码, 补码 详解
    位移运算符
    ASP.NET中httpmodules与httphandlers全解析
    MySQL count
    真正的能理解CSS中的line-height,height与line-height
    IfcEvent
    IfcWorkCalendarTypeEnum
    IfcSingleProjectInstance
    转换模型
    IfcTypeProduct
  • 原文地址:https://www.cnblogs.com/xxbbkk/p/14817897.html
Copyright © 2011-2022 走看看