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;
    }
    
  • 相关阅读:
    POJ 2923 Relocation (状态压缩,01背包)
    HDU 2126 Buy the souvenirs (01背包,输出方案数)
    hdu 2639 Bone Collector II (01背包,求第k优解)
    UVA 562 Dividing coins (01背包)
    POJ 3437 Tree Grafting
    Light OJ 1095 Arrange the Numbers(容斥)
    BZOJ 1560 火星藏宝图(DP)
    POJ 3675 Telescope
    POJ 2986 A Triangle and a Circle
    BZOJ 1040 骑士
  • 原文地址:https://www.cnblogs.com/wdt1/p/13775604.html
Copyright © 2011-2022 走看看