zoukankan      html  css  js  c++  java
  • b_lq_递增三元组(排序+双指针 / 手写lower/upper_bound)

    递增三元组

    请你统计有多少个三元组 (i,j,k) 满足:

    • 1≤i,j,k≤N
      Ai<Bj<Ck

    排序+双指针

    思路
    排序A、B、C,然后固定B的元素B[i],在A里找小于B[i]的数的个数 a、C里找大于B[i]的数的个数 b,对答案的贡献是:a*b

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    int n, a[N], b[N], c[N];
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n;
        for (int i=0; i<n; i++) cin>>a[i];
        for (int i=0; i<n; i++) cin>>b[i];
        for (int i=0; i<n; i++) cin>>c[i];
        sort(a,a+n), sort(b,b+n), sort(c,c+n);
        
        ll ans=0, j=0, k=0;
        for (int i=0; i<n; i++) {
            while (j<n && a[j]<b[i]) j++;
            while (k<n && b[i]>=c[k])k++;
            ans+=j*(n-k);
        }
        cout<<ans;
        return 0;
    }
    

    排序+lower/upper_bound

    这是初始版本的代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    ll n,ans,a[N],b[N],c[N];
    int lower_bound0(ll t[], ll x) { //第一个≥x
        int l=1, r=n+5; //数组下标从0开始
        while (l<r) {
           int m=l+r>>1;
           if (t[m]>=x) r=m; //≥的时候需要取到m,因为有可能m就是唯独一个≥x的了,所以要保证
           else l=m+1; //==x都不符合,那m这个位置就不可能>x
        }
        return l;
    }
    int upper_bound0(ll t[], ll x) { //第一个>x
        int l=1, r=n+1;
        while (l<r) {
            int m=l+r>>1;
            if (t[m]>x) r=m;
            else l=m+1; 
        }
        return l;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n; 
        for (int i=1; i<=n; i++) cin>>a[i]; sort(a+1,a+n+1);
        for (int i=1; i<=n; i++) cin>>b[i]; 
        for (int i=1; i<=n; i++) cin>>c[i]; sort(c+1,c+n+1);
        for (int i=1; i<=n; i++) {
            ll j=lower_bound0(a, b[i])-1, k=n-upper_bound0(c, b[i])+1;
            ans+=j*k;
        }
        cout<<ans;
        return 0;
    }
    

    顺序三元组

    给定n个元素,至于为[1,3]问有多少个元素能组成满足以下条件的三元组:

    • i<j<k,a[i]<a[j]<a[k]

    思路:思维题一道,先统计出3的个数c3,顺序遍历一遍数组,遇到3,c3则减去1,这样可以保证遇到2时,c3都是2后面的3

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    ll n,a[N],ans,c1,c2,c3;
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n; for (int i=0; i<n; i++) cin>>a[i], c3+=a[i]==3;
        for (int i=0; i<n; i++) {
            if (a[i]==1) c1++;
            else if (a[i]==3) c3--;
            else ans+=c1*c3;
        }
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    centos“You don't have permission to access /index.html on this server.”
    使用yum来安装或卸载CentOS图形界面包
    PHP上IIS上显示服务器应用程序不可用
    Windows 2003 远程桌面连接数超过最大连接数终极解决方案
    perl清理电脑上重复的文件
    wordpress在IIS6上首页访问不了
    WordPress首页出现循环重定向解决办法四则(转载)
    windows server 2003 如何在远程链接时更改用户密码
    Ubuntu下安装php5gd库,支持jpg、png、gif等格式图片处理
    wordpress设置用163邮箱账号发送邮件
  • 原文地址:https://www.cnblogs.com/wdt1/p/13775604.html
Copyright © 2011-2022 走看看