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:
- x = 1, y = 2 (season 1 episode 2
season 2 episode 1); - x = 2, y = 3 (season 2 episode 3
season 3 episode 2); - x = 1, y = 3 (season 1 episode 3
season 3 episode 1).
In the third example:
- x = 1, y = 2 (season 1 episode 2
season 2 episode 1); - x = 1, y = 3 (season 1 episode 3
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), '\0', 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("\n");}}}
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("\n");}}}
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\n", ans[i]);
}
printf("%lld\n", temp);
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
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';
}
}
}
Educational Codeforces Round 41 967 E. Tufurama (CDQ分治 求 二维点数)的更多相关文章
- BOI2007 Mokia | cdq分治求二维点数模板
题目链接:戳我 也没什么,其实主要就是为了存一个求二维坐标上矩形内点的个数的模板.为了之后咕咕咕地复习使用 不过需要注意的一点是,树状数组传x的时候可千万不要传0了!要不然会一直死循环的...qwqw ...
- Educational Codeforces Round 41
Educational Codeforces Round 41 D. Pair Of Lines 考虑先把凸包找出来,如果凸包上的点数大于\(4\)显然不存在解,小于等于\(2\)必然存在解 否则枚 ...
- Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]
洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...
- Codeforces Round #371 (Div. 1) D. Animals and Puzzle 二维倍增
D. Animals and Puzzle 题目连接: http://codeforces.com/contest/713/problem/D Description Owl Sonya gave a ...
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- Educational Codeforces Round 41 E. Tufurama (961E)
[题解] 第一眼看题飞快地想到一种做法,然后假掉了. 这道题其实是主席树的模板题来着.但是也有别的水法. 我们可以发现每个位置的查询区间是[1,min(a[i],i-1)],所以我们可以把查询区间按照 ...
- Educational Codeforces Round 41 (Rated for Div. 2)
这场没打又亏疯了!!! A - Tetris : 类似俄罗斯方块,模拟一下就好啦. #include<bits/stdc++.h> #define fi first #define se ...
- Educational Codeforces Round 41 (Rated for Div. 2) ABCDEF
最近打的比较少...就只有这么点题解了. A. Tetris time limit per test 1 second memory limit per test 256 megabytes inpu ...
- Educational Codeforces Round 41 A B C D E
A. Tetris 题意 俄罗斯方块,问能得多少分. 思路 即求最小值 Code #include <bits/stdc++.h> #define F(i, a, b) for (int ...
随机推荐
- docker之容器日志存储位置及把运行日志记录至文件
参考:https://www.cnblogs.com/YatHo/p/7866029.html docker启动后日志会在以下位置 /var/lib/docker/containers/容器ID/容器 ...
- Andrew Ng机器学习课程10
Andrew Ng机器学习课程10 a example 如果hypothesis set中的hypothesis是由d个real number决定的,那么用64位的计算机数据表示的话,那么模型的个数一 ...
- Andrew Ng机器学习课程7
回顾 通过定义训练集S={(x(i),y(i));i=1,2,...,m}与线性决策平面(w,b)之间的function margin γ^和geometric margin γ .好的分类决策平面特 ...
- 说说Spring XML的头
部分内容截取自(http://blog.csdn.net/zhch152/article/details/8191377,http://iswift.iteye.com/blog/1657537) 在 ...
- 第07组 Alpha冲刺(1/4)
队名:秃头小队 组长博客 作业博客 组长徐俊杰 过去两天完成的任务:完成人员分配,初步学习Android开发 Github签入记录 接下来的计划:继续完成Android开发的学习,带领团队进行前后端开 ...
- 利用单臂路由实现vlan间路由
本实验模拟公司场景 通过路由器实现不同vlan部门间通讯,拓扑图如下
- 学习笔记:oracle学习三:SQL语言基础之sql语言简介、用户模式
目录 1.sql语言简介 1.1 sql语言特点 1.2 sql语言分类 1.3 sql语言的编写规则 2.用户模式 2.1 模式与模式对象 2.2 实例模式scott 本系列是作为学习笔记,用于记录 ...
- PCA分析的疑问
R 与python scikit-learn PCA的主成分结果有部分是反的 通过R和python分别计算出来的PCA的结果存在某些主成分的结果是相反的,这些结果是没有问题的,只是表示这个分量被反转了 ...
- JAVA 后台面试之操作系统问题集锦
1.进程和线程以及他们的区别 2.进程间通信的几种方式 3.线程同步的方式 4.死锁 5.分页和分段有什么区别?(内存管理) 6.操作系统中进程调度的策略有哪几种? 7.页面置换算法: 8.系统颠簸 ...
- Echarts 不能百分比显示或显示有问题
1,设折线图宽为100%(如:容器div的class=“RiBarBot”宽为880px),刚初始化时隐藏折线图(或后期刷新.隐藏与显示折线图时),当点击显示折线图时,获取到的宽只有100px,并不是 ...