zoukankan      html  css  js  c++  java
  • Codeforces 961E 树状数组,思维

    E. Tufurama

    题意:
    n 个数 a[],要你找有多少个点对(x, y),其中 x<y,a[x]>=y,a[y]>=x 。
    tags:
    1】比较直观的一种做法,离散化,然后按 min(a[y], y-1) 排序,排序后对于每一个询问,我们更新树状数组到 min(a[y], y-1) 即可。查询就是 Sum(N-1)-Sum(y-1) 。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 500005;
    
    ll  bit[N];
    void Add(int x, ll y) {
        for( ; x<N; x+=x&-x) bit[x] += y;
    }
    ll  Sum(int x) {
        ll  ret = 0; for( ; x; x-=x&-x) ret += bit[x]; return ret;
    }
    
    int n;
    ll  a[N];
    struct Item {
        ll  ai, bi; int id;
        bool friend operator < (Item a, Item b) {
            return a.bi < b.bi;
        }
    } p[N];
    
    map< ll, int > mp;   int tot;
    int get_id(ll x) {
        return  (mp.find(x)==mp.end()) ? (mp[x]=++tot) : mp[x];
    }
    ll  b[N];
    void Init_id() {
        int cnt = 0;
        rep(i,1,n) b[++cnt]=a[i], b[++cnt]=i;
        b[++cnt] = 0;
        sort(b+1, b+1+cnt);
        rep(i,1,cnt) get_id(b[i]);
    }
    
    int main()
    {
        scanf("%d", &n);
        rep(i,1,n) {
            scanf("%lld", &a[i]);
            p[i] = (Item){ a[i], min(1LL*(i-1), a[i]), i };
        }
        Init_id();
        sort(p+1, p+1+n);
        ll  ans = 0;
        int now = 1;
        rep(i,1,n)
        {
            for( ; now<=p[i].bi; ++now) Add(get_id(a[now]), 1);
            ans += Sum(N-1)-Sum(get_id(p[i].id-1));
        }
        printf("%lld
    ", ans);
    
        return 0;
    }
    

    2】还有一种更灵活的做法,把每个 x 存入到对应的 a[x] (如a[x]>n就当作n处理)里,然后 for(y) 从 n 到 1 ,对于每个 y 我们在对应的所有 x 上 +1 ,然后直接询问 Sum(min(y-1, a[y])) 就好。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 500005;
    
    ll  bit[N];
    void Add(int x, ll y) {
        for( ; x<N; x+=x&-x) bit[x]=(bit[x]+y);
    }
    ll  Sum(int x) {
        ll  ret = 0; for( ; x; x-=x&-x) ret=(ret+bit[x]); return ret;
    }
    
    int n, a[N];
    vector< int > ve[N];
    int main()
    {
        scanf("%d", &n);
        rep(i,1,n) {
            scanf("%d", &a[i]);
            if(a[i]<n) ve[a[i]].PB(i);
            else  ve[n].PB(i);
        }
        ll  ans = 0;
        per(i,n,1) {
            for(int x : ve[i]) Add(x, 1);
            ans += Sum(min(i-1, a[i]));
        }
        printf("%lld
    ", ans);
    
        return 0;
    }
    
  • 相关阅读:
    咱家自己的vim配置
    Oauth2手册 第一章
    tcpdf 将网页生成pdf
    Lua 学习记事本
    Lua中的table函数(转)
    Lua常用函数
    将显示对象变成黑白
    Flash 3D 基础
    高等物理:数值积分
    Camera类的基本使用
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8732923.html
Copyright © 2011-2022 走看看