挺巧妙的数据结构题(不过据说这是一种套路?

E. Tufurama

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·10^5) — the number of seasons.

The second line contains n integers separated by space a1, a2, ..., an (1 ≤ ai ≤ 10^9) — 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.


题目大意

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

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


看上去很可做的样子,对吧……

题目分析

基础的暴力

从1..n季,每一季都分别判断对答案的贡献。

例如对于 4 \n 3 5 1 2 ,依次检查(1,2)是否存在(2,1);(1,3)是否存在(3,1)……

首先发现a[i]对于答案的贡献最大也就是到n为止,那么读入时候先取个min(n)。

考虑一下check()是O(n)的,所以总复杂度是O(n²)的。

BIT做法

像很多其他题一样,对于这样的、关于元素大小关系之间的限制的题目,先排个序总是能够解决个一维限制掉去的。

我们使用一个结构体node x,x.i表示季数;x.a表示该季的集数。首先对x.a排序。那么就变成这个样子:

p[].a(j)  3  5  1  2p[].i(i)  1  2  3  4  |  |p[].a(j)  1  2  3  4 (取min之后)p[].i(i)  3  4  1  2

先考虑每次的统计,那么只要ans+=query(a[i])就可以了。意思就是说ans加上1..a[i]季的贡献(其中每一季的贡献要么是0要么是1,但是由于之后会有修改,所以我们用BIT维护)

接着考虑修改,设立一个now指向当前最小合法的p[]。这个now用来更新那些已经 过气 没有贡献的答案。

这里「没有贡献的答案」指的是p[now].a<i的情况。说人话就是p[now]的电视剧集数太小了,已经不会再有贡献了,因此now++,判断下一个p[]是否可能会对答案有贡献。个人感觉有那么一点相似 单调队列 和 wqs二分 的情况(但是我不是非常清楚)?

为了去除这些没有贡献的季数的影响,我们只需将p[now].i位置在树状数组上-1即可。意思是说这个季数在之后的统计上都不会有贡献了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 long long ans;
 4 int n,now,a[200035];
 5 struct node
 6 {
 7     int a,i;
 8     bool operator < (node &xx) const
 9     {
10         return a < xx.a;
11     }
12 }p[200035];
13 int f[200035];
14 int read()
15 {
16     char ch = getchar();int num = 0;
17     for (; !isdigit(ch); ch = getchar());
18     for (; isdigit(ch); ch = getchar())
19         num = (num<<3)+(num<<1)+ch-48;
20     return num;
21 }
22 int lowbit(int x){return x&-x;}
23 void add(int x, int c){for (; x<=n+1; x+=lowbit(x))f[x]+=c;}
24 int query(int x)
25 {
26     int ret = 0;
27     for (; x; x-=lowbit(x))
28         ret += f[x];
29     return ret;
30 }
31 int main()
32 {
33     n = read();now = 1;
34     for (int i=1; i<=n; i++)
35         a[i] = min(read(), n+1), p[i].a = a[i], p[i].i = i, add(i, 1);
36     sort(p+1, p+n+1);
37     for (int i=1; i<=n; i++)
38     {
39         while (now<=n && p[now].a < i)add(p[now++].i, -1);
40         ans += query(a[i]);
41         if (a[i] >= i)ans--;
42     }
43     cout << ans / 2 << endl;
44     return 0;
45 }

另附其他做法

其他人用BIT维护也挺巧妙的(但是我觉得初看时候有点云里雾里啊)

1.Educational Codeforces Round 41 E. Tufurama (961E)  BIT做法

2.Codeforces 961E - Tufurama 【树状数组】  BIT做法

3.Codeforces - 961E Tufurama  set+BIT

4.CF 961E Tufurama  跟我一样的

END

转载于:https://www.cnblogs.com/antiquality/p/8746718.html

【树状数组】CF961E Tufurama相关推荐

  1. 洛谷 P5057 [CQOI2006]简单题(树状数组)

    嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ...

  2. Color the ball(HDU1556)树状数组

    每次对区间内气球进行一次染色,求n次操作后后所有气球染色次数. 树状数组,上下区间更新都可以,差别不大. 1.对于[x,y]区间,对第x-1位减1,第y位加1,之后向上统计 #include<b ...

  3. 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组

    [BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...

  4. Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)

    题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...

  5. poj_3067 树状数组

    题目大意 左右两个竖排,左边竖排有N个点,从上到下依次标记为1,2,...N; 右边竖排有M个点,从上到下依次标记为1,2....M.现在从K条直线分别连接左边一个点和右边一个点,求这K条直线的交点个 ...

  6. hdu 1166 敌兵布阵(树状数组)

    题意:区间和 思路:树状数组 #include<iostream> #include<stdio.h> #include<string.h> using names ...

  7. Equalizing Two Strings 冒泡排序or树状数组

    首先考虑排序后相等 如果排序后相等的话就只考虑reverse长度为2的,所以a或者b排序后存在相邻两个字母相等的话就puts YES,n>26也直接puts YES 不然的话就假设c为a,b排完 ...

  8. Hdu 6534 Chika and Friendly Pairs 莫队算法+树状数组

    题目链接 题意求给区间[L,R]中有少对(i,j)满足i<j且abs(a[i]-a[j])<=k. 首先来说暴力的方法就是离散化,然后用树状数组来维护,但是m次询问,m很大,所以说一定会t ...

  9. HDU - 5877 Weak Pair 2016 ACM/ICPC 大连网络赛 J题 dfs+树状数组+离散化

    题目链接 You are given a rootedrooted tree of NN nodes, labeled from 1 to NN. To the iith node a non-neg ...

最新文章

  1. C++从键盘读取字符
  2. 报错解决:-bash: export: `g++11=g++': not a valid identifier
  3. js 中导出excel 较长数字串会变成科学计数法
  4. shiro学习(13):springMVC结合shiro完成认证
  5. 在linux下vcd光盘提取,linux下抓取Vcd的视频文件[Linux安全]
  6. 贪心算法详细讲解(附例题,一看就会)
  7. 关于ie6常见浏览器兼容问题
  8. fid和is_【深度学习】生成式对抗网络(GAN)的常见评价指标:IS/FID/JS散度
  9. 计算机网络物理层之宽带接入技术
  10. 和计算机相关的祝福语,祝福语精选
  11. 如何计算样本权重和类别权重? 样本权重怎样起作用?
  12. 如何利用python整合excel_如何使用Python处理Excel
  13. CS61A fa2021 Composing Programs 2.8 Efficiency 效率
  14. 光盘如何重装系统教程
  15. 中兴olt-c300常用命令
  16. 请问汽车CD接线各个的字母代表什么,ACC,ILL,RR,FR,FL,RLANT,B/U,NC,CND,真诚的谢谢了!
  17. Docker启动MySql时Exited (1) 8 seconds ago或者Error response from daemon: Container xx is not running的解决方法
  18. 采用数据分析利用加速度计进行电梯速度估算之模型建立
  19. 从事家电行业17年,分享下我的购买心得:哪些品牌电器值得你购买
  20. 【结构型】组合模式(Composite)

热门文章

  1. GBT19056精要
  2. oracle 根据分隔符提取,oracle自定义函数按照某个分隔符拆分字符串
  3. php print r用法,php中echo(),print(),print_r()用法
  4. oracle 锁表如何解决_Java高并发解决什么方式
  5. LeetCode 2114. 句子中的最多单词数
  6. LeetCode 426. 将二叉搜索树转化为排序的双向链表(BST中序循环遍历)
  7. 【Python基础知识-pycharm版】第十节_异常
  8. python中if命令简单介绍及注意事项(含笔记)
  9. Codeforces Round #702 (Div. 3)解题报告
  10. Educational Codeforces Round 103 (Rated for Div. 2)A~E解题报告