• [luogu4755]Beautiful Pair


    [luogu4755]Beautiful Pair

    luogu
    第一次写最大值分治感觉有点丑
    每次找到最大值mid,扫小的一边,主席树查大的一边小于等于(frac{a[mid]}{a[i]})的个数
    复杂度(O(nlog^2n))
    md主席树空间又挂了几次(修改次数*log值域)

    #define ll long long
    #include<bits/stdc++.h>
    using namespace std;
    const int _=1e5+5;
    int re(){
        int x=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    ll ans;
    int n,m,tot;
    int a[_],rt[_],lg[_],s[_*33],ls[_*33],rs[_*33],f[20][_];
    void upd(int&x,int l,int r,int k){
        s[++tot]=s[x]+1;ls[tot]=ls[x];rs[tot]=rs[x];
        x=tot;if(l==r)return;int mid=l+r>>1;
        if(k<=mid)upd(ls[x],l,mid,k);
        else upd(rs[x],mid+1,r,k);
    }
    int qsum(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return s[x];
        int mid=l+r>>1,res=0;
        if(ql<=mid)res=qsum(ls[x],l,mid,ql,qr);
        if(qr>mid)res+=qsum(rs[x],mid+1,r,ql,qr);
        return res;
    }
    int qmax(int l,int r){
        int k=lg[r-l+1],x=f[k][l],y=f[k][r-(1<<k)+1];
        return a[x]>a[y]?x:y;
    }
    void solve(int l,int r){
        int mid=qmax(l,r);
        if(mid-l<r-mid){
            for(int i=l;i<mid;i++){
                ans+=qsum(rt[r],1,m,1,a[mid]/a[i]);
                ans-=qsum(rt[mid-1],1,m,1,a[mid]/a[i]);
            }
            ans+=qsum(rt[r],1,m,1,1);
            ans-=qsum(rt[mid],1,m,1,1);
        }
        else{
            for(int i=mid+1;i<=r;i++){
                ans+=qsum(rt[mid],1,m,1,a[mid]/a[i]);
                ans-=qsum(rt[l-1],1,m,1,a[mid]/a[i]);
            }
            ans+=qsum(rt[mid-1],1,m,1,1);
            ans-=qsum(rt[l-1],1,m,1,1);
        }
        if(l<mid-1)solve(l,mid-1);
        if(mid+1<r)solve(mid+1,r);
    }
    int main(){
        n=re();m=1e9;
        for(int i=1;i<=n;i++)a[i]=re();
        for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++){
            ans+=(a[i]==1);
            rt[i]=rt[i-1];f[0][i]=i;
            upd(rt[i],1,m,a[i]);
        }
        for(int i=1;i<=lg[n];i++)
            for(int j=1;j+(1<<i)-1<=n;j++){
                int x=f[i-1][j],y=f[i-1][j+(1<<(i-1))];
                f[i][j]=a[x]>a[y]?x:y;
            }
        solve(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Visual Studio一直弹出“未将对象引用设置到对象的实例”对话框的处理
    C#如何将十六进制数字符串转byte[]?
    steam游戏存档迁移
    Java实现行列式计算
    Python中单引号、双引号、三引号的区别
    git基本使用方法
    windows(hexo)使用git时出现:warning: LF will be replaced by CRLF
    steam相关插件
    linux的后台运行相关命令
    Ubuntu下启动/重启/停止apache服务器
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9904303.html
Copyright © 2020-2023  润新知