zoukankan      html  css  js  c++  java
  • Luogu P4755 Beautiful Pair

    题目
    预处理(L[p])表示其左边第一个数值大于等于它的数的位置加一,(R[p])表示其右边第一个数值大于等于它的数的位置减一。
    考虑对于(p),最大值为(p)的区间为([L[p],R[p]]),也就是左端点在([L[p],p]),右端点在([p,R[p]])
    我们取其中长度小的一段。
    比如说([L[p],p])这一段比较短,那么(forall iin[L[p],p]),答案会加上([p,R[p]])中大于等于(lfloorfrac{a[p]}{a[i]} floor)的数的个数。
    将其容斥一下转化为([1,R[p]])中大于(lfloorfrac{a[p]}{a[i]} floor)的数的个数减去([1,p-1])中大于等于(lfloorfrac{a[p]}{a[i]} floor)的数的个数。
    如果([p,R[p]])比较短也做同样的操作。
    可以证明,复杂度不超过(nlog n)
    我们选择离散化后使用树状数组维护。

    #include<bits/stdc++.h>
    #define P pair<int,int>
    #define mp make_pair
    #define fir first
    #define sec second
    #define pb push_back
    #define LL long long
    using namespace std;
    const int N=100007;
    int a[N],t[N],L[N],R[N],n,m;
    LL s[N];
    P stk[N];
    vector<int>vec[N];
    int abs(int a){return a<0? -a:a;}
    int read(){int x;scanf("%d",&x);return x;}
    int lowbit(int x){return x&-x;}
    int Find(int x){return x>=t[n]? n:upper_bound(t+1,t+m+1,x)-(t+1);}
    LL query(int x)
    {
        LL sum=0;
        while(x) sum+=s[x],x-=lowbit(x);
        return sum;
    }
    void update(int x,int v){while(x<=n)s[x]+=v,x+=lowbit(x);}
    int main()
    {
        n=read();int i,j,top;LL ans=0;
        for(i=1;i<=n;++i) a[i]=t[i]=read();
        for(i=1,top=0;i<=n;++i)
        {
    	while(top&&stk[top].fir<a[i]) --top;
    	L[i]=(top? stk[top].sec+1:1),stk[++top]=mp(a[i],i);
        }
        for(i=n,top=0;i;--i)
        {
    	while(top&&stk[top].fir<=a[i]) --top;
    	R[i]=(top? stk[top].sec-1:n),stk[++top]=mp(a[i],i);
        }
        for(i=1;i<=n;++i)
    	if(i-L[i]<=R[i]-i) for(vec[i-1].pb(-1),vec[R[i]].pb(1),j=L[i];j<i;++j) vec[i-1].pb(-a[i]/a[j]),vec[R[i]].pb(a[i]/a[j]);
            else for(vec[L[i]-1].pb(-1),vec[i].pb(1),j=i+1;j<=R[i];++j) vec[L[i]-1].pb(-a[i]/a[j]),vec[i].pb(a[i]/a[j]);
        sort(t+1,t+n+1),m=unique(t+1,t+n+1)-(t+1);
        for(i=1;i<=n;++i) a[i]=lower_bound(t+1,t+m+1,a[i])-t;
        for(i=1;i<=n;i++) for(update(a[i],1),top=vec[i].size(),j=0;j<top;++j) vec[i][j]<0? ans-=query(Find(abs(vec[i][j]))):ans+=query(Find(abs(vec[i][j])));
        return !printf("%lld",ans);
    }
    
  • 相关阅读:
    Linux getcwd()的实现【转】
    关于__GNU_SOURCE 这个宏---如何开启【转】
    UBI 文件系统移植 sys 设备信息【转】
    Linux USB驱动框架分析【转】
    局部变量、全局变量、堆、堆栈、静态和全局【转】
    C语言字节对齐问题详解【转】
    usb驱动的基本结构和函数简介【转】
    makefile函数集锦【转】
    非常好!!!Linux源代码阅读——内核引导【转】
    JQuery日记6.9 Promise/A之Callbacks
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11512299.html
Copyright © 2011-2022 走看看