zoukankan      html  css  js  c++  java
  • 洛谷p4755 Beautiful Pair

    神仙分治题,
    我们假设当前分到了([l,r])
    那么我们就可以做一个假设:设(p)为这个区间内最大的值(mx),其编号为(p)
    那么这里有一部分的答案就是([l,p - 1] + [p + 1,r])
    为什么?其实这个想一想就知道。
    因为我们一般是不会用这个数跟其他的数结合的。
    那么我们就结束了左边和右边单独计算的情况。
    那么还有就是左边和右边混起来的情况。
    这个其实也很好解决。
    我们已经知道了当前的最大值,只需要枚举左边然后算一下有多少个数小于(frac{mx}{a_l})((l)为当前枚举到的左边界)。
    这里可以离散化然后用树状数组完成(具体操作省去)。
    同样的,算一下([l,p - 1])时的情况,因为上面一轮算过了([p + 1,r]),所以这里只要计算一下边界为(p)就行了。
    具体复杂度应该接近于(O(n log n))
    不过极限情况下是能够到达(O(n ^ 2))
    不过我觉得应该没有人会卡你,
    能过就够了。

    #include <bits/stdc++.h>
    
    const int maxn = 1e5 + 10;
    typedef long long ll;
    
    template<class t> inline void read(t& res) {
        res = 0;  bool neg = 0;  char ch = getchar();
        while(!isdigit(ch))
            neg |= ch == '-', ch = getchar();
        while(isdigit(ch))
            res = (res << 1) + (res << 3) + (ch & 15), ch = getchar();
        if(neg)
            res = -res;   
    }
    template<class t1,class t2> inline void cmax(t1& a,t2 b) {
        if(a < b)
            a = b;  
    } 
    template<class t> inline t _abs(t x) {
        return x < 0 ? -x : x;  
    }
    
    int n, m, i, j, k;  
    int a[maxn], num[maxn], MX, d[maxn];    
    
    struct node {
        int id, va;   
        node() { id = va = 0; }
        node(int _id,int _va) {
            id = _id;  va = _va;
        }  
        inline friend bool operator < (node a,node b) {
            return a.va < b.va;  
        }
    } f[maxn]; 
     
    inline void lsh() {
        std::sort(f + 1,f + n + 1);
        int cnt = 0;
        for(int i = 1;i <= n;i++) {
            if(f[i].va != f[i - 1].va)
                cnt++;
            num[ f[i].id ] = cnt;    
        }
        for(int i = 1;i <= n;i++)
            f[i] = node(num[i],a[i]);
        std::sort(f + 1,f + n + 1);   
        std::sort(d + 1,d + n + 1);   
    }
    
    struct binary_index_tree {
        int c[maxn];     
        inline void add(int x,int y) {
            while(x <= n)
                c[x] += y, x += x & -x;     
        }          
        inline int ask(int x) {  
            int res = 0;  
            while(x)
                res += c[x], x -= x & -x;    
            return res;          
        }
    } A;  
    
    inline int get(int x) {
        if(x > d[n])
            return 0;
        else
            return f[std::upper_bound(d + 1,d + n + 1,x) - d - 1].id;   
    }
    
    ll calc(ll l,ll r) {
    	if(l > r)
    		return 0;   
        if(l == r)
            return a[l] == 1;
        ll res = 0, mid = (l + r) >> 1, mx = -1, pos;
        for(int i = l;i <= r;i++) {
            if(a[i] > mx) {
                mx = a[i];          
                pos = i;   
            } else if(a[i] == mx && (_abs(i - mid) < _abs(pos - mid))) {
                pos = i;   
            } 
        }  
        res += calc(l,pos - 1);  
        res += calc(pos + 1,r);  
        for(int i = pos + 1;i <= r;i++)
            A.add(num[i],1);     
        for(int i = l;i <= pos;i++)
            res += A.ask(get(mx / a[i]));   
        for(int i = pos + 1;i <= r;i++)
            A.add(num[i],-1);
        for(int i = l;i <= pos - 1;i++)
            A.add(num[i],1);
        res += A.ask(get(mx / a[pos]));  
        for(int i = l;i <= pos - 1;i++)
            A.add(num[i],-1);
        if(a[pos] == 1)
            res++;
        return res;  
    }
    
    int main() {
        read(n);
        for(int i = 1;i <= n;i++)
            read(a[i]), f[i] = node(i,a[i]), d[i] = a[i];  
        lsh();     
        printf("%lld
    ",calc(1,n));   
    }
    
  • 相关阅读:
    美国州名来源
    SQL Constraint/Index
    英语中的 姓氏/Surname
    GNU glibc
    英语人名探源/字母升序排列
    About 'atoi'
    封装一个类似jquery的ajax方法
    函数柯里化
    AngularJS实现TodoMVC
    webpack简单使用
  • 原文地址:https://www.cnblogs.com/Sai0511/p/11190254.html
Copyright © 2011-2022 走看看