树状数组 简单题 cf 961E

    题目链接 : https://codeforces.com/problemset/problem/961/E

        

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 ai episodes (numbered 1 through ai). 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, ..., an (1 ≤ ai ≤ 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
5 1 2 3 4 5
Output
Copy
0
Input
Copy
3 8 12 7
Output
Copy
3
Input
Copy
3 3 2 1
Output
Copy
2
Note

Possible pairs in the second example:

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

In the third example:

  1. x = 1, y = 2 (season 1 episode 2 season 2 episode 1);
  2. x = 1, y = 3 (season 1 episode 3 season 3 episode 1).
扫描二维码关注公众号,回复: 4913357 查看本文章

      题目大意  : (首先这个题有一个电视剧) 输入n (代表一共有 多少季)之后有n个数每个数 代表这季有多少集,如果 x 季 y集 和 y 季 x集能

                同时被找到就说明有一个错误。例如  n = 2   a1=2  a2=3 有 1 季 2 集 和 2 季 1 集 说明有一个错误则输出 1 .

      思路 : 保证 ax>=y x<y ay>=x 这三个条件,如果只是前两个的话树状数组完全可以满足,但如果加上第三个条件的话,树状数组没法满足

          所以想到先把第三个条件预处理出来存到vector中,然后依次解决.vector中压入v [ min( i-1, a [ i ] ) ] . push_back( i ),为什么要这么

          写呢首先a[ i ] =min  ( a[ i ] , n  ),这个不难理解因为如果a [ i ]  > n 的话比n 大的没有意义因为最多就到n季。然后为什么vector中要

          以 min  ( i - 1 , a [ i ] ) 为一维呢,这里是指当前 i 能到达的极限,极限有两种情况{ 1.如果ai大的话可以通过之后的 i 来查找当前剩

          余的ai,2.如果 i 大的话说明当前这个值最多能达到ai(可以手动推一下) } 那为什么是 i -1 呢?因为如果 i = 5 , a5=3 的话 i 要从 4

          开始查因为和自己查没有意义还会出错.  

          这里要压入 i 是为了之后找 ax>=i 因为在树状数组求逆序数是 sum(MAX_N)-sum ( ai ) , 这个是求ax>ai,而我们要求的是 ax> = i  

          所以我们变成了 sum(MAX_N)-sum(i),这里 x < i 一直成立.

          还有就是ai的范围是1e9 太大了,在这道题中当 ai>n 和ai=n 是等价的,因为一共就n那么大,如果ai比n大的话找不到更大的和ai对应

          所以是等价的.

#include<bits/stdc++.h>
using namespace std;
int x[200020];
int szsz[200020];
int m,n;
vector <int> vic[200020];
int lowbit(int a){
    return a&(-a);
}
void add(int a){
    for(int i=a;i<=200015;i+=lowbit(i)){
        szsz[i]+=1;
    }
}
int qiuhe(int a){
    int ans=0;
    for(int i=a;i>=1;i-=lowbit(i)){
        ans+=szsz[i];
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&x[i]);
        x[i]=min(n,x[i]);
        vic[min(i-1,x[i])].push_back(i);
    }
    memset(szsz,0,sizeof(szsz));
    long long sum=0;
    for(int i=1;i<=n;i++){
        add(x[i]);
        for(int j=0;j<vic[i].size();j++){
            sum+=qiuhe(n)-qiuhe(vic[i][j]-1);
        }
    }
    printf("%lld\n",sum);
    return 0;
}

   

猜你喜欢

转载自www.cnblogs.com/fzw1523/p/10267902.html
今日推荐