• Educational Codeforces Round 41 967 E. Tufurama (CDQ分治 求 二维点数)


    Educational Codeforces Round 41 (Rated for Div. 2)

    E. Tufurama (CDQ分治 求 二维点数)

    time limit per test

    2 seconds

    memory limit per test

    256 megabytes

    input

    standard input

    output

    standard output

    One day Polycarp decided to rewatch his absolute favourite episode of well-known TV series "Tufurama". He was pretty surprised when he got results only for season 7 episode 3 with his search query of "Watch Tufurama season 3 episode 7 online full hd free". This got Polycarp confused — what if he decides to rewatch the entire series someday and won't be able to find the right episodes to watch? Polycarp now wants to count the number of times he will be forced to search for an episode using some different method.

    TV series have n seasons (numbered 1 through n), the i-th season has a**i episodes (numbered 1 through a**i). Polycarp thinks that if for some pair of integers x and y (x < y) exist both season x episode y and season y episode x then one of these search queries will include the wrong results. Help Polycarp to calculate the number of such pairs!

    Input

    The first line contains one integer n (1  ≤ n  ≤  2·105) — the number of seasons.

    The second line contains n integers separated by space a1, a2, ..., a**n (1 ≤ a**i ≤ 109) — number of episodes in each season.

    Output

    Print one integer — the number of pairs x and y (x < y) such that there exist both season x episode y and season y episode x.

    Examples

    input

    Copy

    51 2 3 4 5
    

    output

    Copy

    0
    

    input

    Copy

    38 12 7
    

    output

    Copy

    3
    

    input

    Copy

    33 2 1
    

    output

    Copy

    2
    

    Note

    Possible pairs in the second example:

    1. x = 1, y = 2 (season 1 episode 2 img season 2 episode 1);
    2. x = 2, y = 3 (season 2 episode 3 img season 3 episode 2);
    3. x = 1, y = 3 (season 1 episode 3 img season 3 episode 1).

    In the third example:

    1. x = 1, y = 2 (season 1 episode 2 img season 2 episode 1);
    2. x = 1, y = 3 (season 1 episode 3 img season 3 episode 1).

    题意:

    有一部电视剧有n季,每一季有ai集。定义二元组(i,j):存在第i季有第j集。求(i,j)与(j,i)同时合法(i<j)的对数。

    真实题意就是:求<i,j>对数,使得a[i]≥j,a[j]≥i并且(i<j)

    思路

    我们对于第i集,我们建立一个二维坐标(i,a[i] )

    通过分析我们发现,对于第i集,可以对答案的贡献就是 ([i+1,a[i]]) 这个区间集中,集数a[j] >= i 的个数。

    我们可以转化为 是询问 二维坐标系中 左下角为((i+1,i)) 右上角是 (([i],n+1)) 的矩阵中包括的点数。

    (a[i]<=i) 时,这个第i集对答案一定为0贡献的,

    所以记得跳过这种情况。

    然后上面就是一个经典的三维偏序问题,我们直接套CDQ分治模板即可。

    此题有更简单的树状数组写法,带更。(因为CDQ直接套板子不费脑子)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    
    inline void getInt(int *p);
    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int op;
    int n;
    const int maxL = 3000010;
    ll tree[maxL];
    int lowbit(int x)
    {
        return -x & x;
    }
    ll ask(int x)
    {
    //    cout << x << " ";
        ll res = 0ll;
        while (x) {
            res += tree[x];
            x -= lowbit(x);
        }
    //    cout << res << endl;
        return res;
    }
    void add(int x, ll val)
    {
    //    cout << x << " " << val << endl;
        while (x < maxL) {
            tree[x] += val;
            x += lowbit(x);
        }
    }
    
    struct node {
        int t;
        int op;
        int x, y;
        int k;
        int val;
        node() {}
        node(int tt, int oo, int xx, int yy, int kk, int vv)
        {
            t = tt;
            op = oo;
            x = xx;
            y = yy;
            k = kk;
            val = vv;
        }
        bool operator<= (const node &bb )const
        {
            if (x != bb.x) {
                return x < bb.x;
            } else {
                return y <= bb.y;
            }
        }
    };
    node a[maxn];
    node b[maxn];
    ll ans[maxn];
    int tot;
    int anstot;
    
    
    void cdq(int l, int r)
    {
        if (l == r) {
            return ;
        }
        int mid = (l + r) >> 1;
        cdq(l, mid);
        cdq(mid + 1, r);
        int ql = l;
        int qr = mid + 1;
        repd(i, l, r) {
            if (qr > r || (ql <= mid && a[ql] <= a[qr])) {
                if (a[ql].op == 1) {
                    add(a[ql].y, a[ql].val);
                }
                b[i] = a[ql++];
            } else {
                if (a[qr].op == 2) {
                    ans[a[qr].val] += a[qr].k * ask(a[qr].y);
                }
                b[i] = a[qr++];
            }
        }
        ql = l;
        qr = mid + 1;
        repd(i, l, r) {
            if (qr > r || (ql <= mid && a[ql] <= a[qr])) {
                if (a[ql].op == 1) {
                    add(a[ql].y, -a[ql].val);
                }
                ql++;
            } else {
                qr++;
            }
        }
        repd(i, l, r) {
            a[i] = b[i];
        }
    }
    int m;
    int c[maxn];
    
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        scanf("%d", &n);
        int x1, x2, y1, y2;
        repd(i, 1, n)
        {
            scanf("%d", &c[i]);
            if (c[i] > n)
                c[i] = n;
            tot++;
    //        cout<<i<<" , "<<c[i]<<endl;
            a[tot] = node(tot, 1, i, c[i], 0, 1);
        }
        repd(i,1,n)
        {
            if(c[i]<=i)
                continue;
            x1 = i + 1;
            y1 = i;
    
            x2 = c[i];
            y2 = n+1;
    //        cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl;
            tot++;
            a[tot] = node(tot, 2, x1 - 1, y1 - 1, 1, ++anstot);
            tot++;
            a[tot] = node(tot, 2, x1 - 1, y2, -1, anstot);
            tot++;
            a[tot] = node(tot, 2, x2, y1 - 1, -1, anstot);
            tot++;
            a[tot] = node(tot, 2, x2, y2, 1, anstot);
        }
        cdq(1, tot);
        ll temp = 0ll;
        repd(i, 1, anstot) {
            temp += ans[i];
    //        printf("%lld
    ", ans[i]);
        }
        printf("%lld
    ", temp);
    
        return 0;
    }
    
    inline void getInt(int *p)
    {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        } else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    显卡关键词
    为照顾IE6尽量不要margin和padding
    如何保证一个类只有一个实例(1)
    显示列表(display list)
    AutoCAD2007与Office2007冲突
    虚函数(1)
    字符串对象的属性
    细读cow.osg
    常量折叠(const folding)与复写传播 (copy propagation)
    .NET Framework 3.5 sp1离线安装
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11886574.html
Copyright © 2020-2023  润新知