【树状数组】CF961E Tufurama
挺巧妙的数据结构题(不过据说这是一种套路?
E. Tufurama
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!
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.
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相关推荐
- 洛谷 P5057 [CQOI2006]简单题(树状数组)
嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ...
- Color the ball(HDU1556)树状数组
每次对区间内气球进行一次染色,求n次操作后后所有气球染色次数. 树状数组,上下区间更新都可以,差别不大. 1.对于[x,y]区间,对第x-1位减1,第y位加1,之后向上统计 #include<b ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)
题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...
- poj_3067 树状数组
题目大意 左右两个竖排,左边竖排有N个点,从上到下依次标记为1,2,...N; 右边竖排有M个点,从上到下依次标记为1,2....M.现在从K条直线分别连接左边一个点和右边一个点,求这K条直线的交点个 ...
- hdu 1166 敌兵布阵(树状数组)
题意:区间和 思路:树状数组 #include<iostream> #include<stdio.h> #include<string.h> using names ...
- Equalizing Two Strings 冒泡排序or树状数组
首先考虑排序后相等 如果排序后相等的话就只考虑reverse长度为2的,所以a或者b排序后存在相邻两个字母相等的话就puts YES,n>26也直接puts YES 不然的话就假设c为a,b排完 ...
- Hdu 6534 Chika and Friendly Pairs 莫队算法+树状数组
题目链接 题意求给区间[L,R]中有少对(i,j)满足i<j且abs(a[i]-a[j])<=k. 首先来说暴力的方法就是离散化,然后用树状数组来维护,但是m次询问,m很大,所以说一定会t ...
- 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 ...
最新文章
- C++从键盘读取字符
- 报错解决:-bash: export: `g++11=g++': not a valid identifier
- js 中导出excel 较长数字串会变成科学计数法
- shiro学习(13):springMVC结合shiro完成认证
- 在linux下vcd光盘提取,linux下抓取Vcd的视频文件[Linux安全]
- 贪心算法详细讲解(附例题,一看就会)
- 关于ie6常见浏览器兼容问题
- fid和is_【深度学习】生成式对抗网络(GAN)的常见评价指标:IS/FID/JS散度
- 计算机网络物理层之宽带接入技术
- 和计算机相关的祝福语,祝福语精选
- 如何计算样本权重和类别权重? 样本权重怎样起作用?
- 如何利用python整合excel_如何使用Python处理Excel
- CS61A fa2021 Composing Programs 2.8 Efficiency 效率
- 光盘如何重装系统教程
- 中兴olt-c300常用命令
- 请问汽车CD接线各个的字母代表什么,ACC,ILL,RR,FR,FL,RLANT,B/U,NC,CND,真诚的谢谢了!
- Docker启动MySql时Exited (1) 8 seconds ago或者Error response from daemon: Container xx is not running的解决方法
- 采用数据分析利用加速度计进行电梯速度估算之模型建立
- 从事家电行业17年,分享下我的购买心得:哪些品牌电器值得你购买
- 【结构型】组合模式(Composite)
热门文章
- GBT19056精要
- oracle 根据分隔符提取,oracle自定义函数按照某个分隔符拆分字符串
- php print r用法,php中echo(),print(),print_r()用法
- oracle 锁表如何解决_Java高并发解决什么方式
- LeetCode 2114. 句子中的最多单词数
- LeetCode 426. 将二叉搜索树转化为排序的双向链表(BST中序循环遍历)
- 【Python基础知识-pycharm版】第十节_异常
- python中if命令简单介绍及注意事项(含笔记)
- Codeforces Round #702 (Div. 3)解题报告
- Educational Codeforces Round 103 (Rated for Div. 2)A~E解题报告