题目描述
有一天Polycarp决定重看他最喜爱的电视剧《Tufurama》。当他搜索“在线全高清免费观看Tufurama第3季第7集”却只得到第7季第3集的结果时,他很惊讶。这让Polycarp感到疑惑——如果有天他决定重看整个系列却无法找到正确的剧集观看,那该怎么办呢?Polycarp现在想统计一下他被迫用不同方案搜索同一剧集的次数。
电视连续剧有nn 季(从11 到nn 编号),第ii 季有a_iai 集(从11 到a_iai 编号)。Polycarp认为如果有一对xx 和yy (x<yx<y ),使第xx 季第yy 集、第yy 季第xx 集存在,那么其中一个搜索就会包含错误的内容。请帮助Polycarp统计这样的数对的数量吧!
输入输出格式
输入格式
第一行,一个整数n(1 leq n leq 2 cdot 10^5)n(1≤n≤2⋅105) ,表示季数。
第二行,nn 个用空格隔开的整数a_1, a_2, ... , a_n (1 leq a_i leq 10^9)a1,a2,...,an(1≤ai≤109) ,表示每一季的集数。
输出格式
只有一行,一个整数,表示xx 和yy (x<yx<y ),使第xx 季第yy 集、第yy 季第xx 集存在的数对的数量。
说明
在样例2中可能的对数:
- x=1, y=2x=1,y=2 (第1季第2集
第2季第1集)
- x=2, y=3x=2,y=3 (第2季第3集
第3季第2集)
- x=1, y=3x=1,y=3 (第1季第3集
第3季第1集)
在样例3中:
- x=1, y=2x=1,y=2 (第1季第2集
第2季第1集)
- x=1, y=3x=1,y=3 (第1季第3集
第3季第1集)
感谢@月见之兔 提供的翻译
题目描述
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 nn seasons (numbered 11 through nn ), the ii -th season has a_{i}ai episodes (numbered 11through a_{i}ai ). Polycarp thinks that if for some pair of integers xx and yy ( x<yx<y ) exist both season xxepisode yy and season yy episode xx then one of these search queries will include the wrong results. Help Polycarp to calculate the number of such pairs!
输入输出格式
输入格式:
The first line contains one integer nn (1<=n<=2·10^{5})(1<=n<=2⋅105) — the number of seasons.
The second line contains nn integers separated by space a_{1},a_{2},...,a_{n}a1,a2,...,an (1<=a_{i}<=10^{9})(1<=ai<=109) — number of episodes in each season.
输出格式:
Print one integer — the number of pairs xx and yy ( x<yx<y ) such that there exist both season xx episode yyand season yy episode xx .
输入输出样例
说明
Possible pairs in the second example:
- x=1x=1 , y=2y=2 (season 1 episode 2
season 2 episode 1);
- x=2x=2 , y=3y=3 (season 2 episode 3
season 3 episode 2);
- x=1x=1 , y=3y=3 (season 1 episode 3
season 3 episode 1).
In the third example:
- x=1x=1 , y=2y=2 (season 1 episode 2
season 2 episode 1);
- x=1x=1 , y=3y=3 (season 1 episode 3
season 3 episode 1).
题解
- 题目大意:给n季的电视剧,每季有a[i]季,问有多少个二元组(i,j)满足存在第i季j集和第j季i集
- 其实就是要求(i,j)满足a[i]>=j,a[j]>=i,i<=j的组的个数
- 因为最多只有n季,所以a[i]对于答案的最大贡献也就只到n,所以可以将所有的a[i]与n取min先
- 然后我们可以以a[i]从小到大排序,将其加入树状数组中
- 先考虑每次的统计,那么只要ans+=query(a[i])就可以了,就是说ans加上1..a[i]季的贡献,每一季的贡献要不就是0/1
- 接着考虑如何修改,维护一个指针now表示当前合法的最小a[i],那么当前不合法的答案就是a[now] <i的情况,也就是集数比当前做的的季数还要小,那么肯定是没有贡献的了,就now++
- 减去他们在树状数组上的贡献,就直接在该为位置-1就好了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define N 200010 5 using namespace std; 6 struct edge {int a,d;}p[N]; 7 int n,l,a[N],sz[N]; 8 long long ans; 9 bool cmp(edge a,edge b) { return a.a<b.a; } 10 void add(int x,int y) { for (;x<=n+1;x+=x&-x) sz[x]+=y; } 11 int query(int x) { int r=0; for (;x;x-=x&-x) r+=sz[x]; return r; } 12 int main() 13 { 14 scanf("%d",&n),l=1; 15 for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]=min(a[i],n+1),p[i].a=a[i],p[i].d=i,add(i,1); 16 sort(p+1,p+n+1,cmp); 17 for (int i=1;i<=n;i++) 18 { 19 while (l<=n&&p[l].a<i) add(p[l++].d,-1); 20 ans+=query(a[i]); if (a[i]>=i) ans--; 21 } 22 printf("%lld",ans/2); 23 }