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:

  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).

题意:

有一部电视剧有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分治 求 二维点数)的更多相关文章

  1. BOI2007 Mokia | cdq分治求二维点数模板

    题目链接:戳我 也没什么,其实主要就是为了存一个求二维坐标上矩形内点的个数的模板.为了之后咕咕咕地复习使用 不过需要注意的一点是,树状数组传x的时候可千万不要传0了!要不然会一直死循环的...qwqw ...

  2. Educational Codeforces Round 41

    Educational Codeforces Round 41  D. Pair Of Lines 考虑先把凸包找出来,如果凸包上的点数大于\(4\)显然不存在解,小于等于\(2\)必然存在解 否则枚 ...

  3. Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]

    洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...

  4. 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 ...

  5. BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)

    Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...

  6. Educational Codeforces Round 41 E. Tufurama (961E)

    [题解] 第一眼看题飞快地想到一种做法,然后假掉了. 这道题其实是主席树的模板题来着.但是也有别的水法. 我们可以发现每个位置的查询区间是[1,min(a[i],i-1)],所以我们可以把查询区间按照 ...

  7. Educational Codeforces Round 41 (Rated for Div. 2)

    这场没打又亏疯了!!! A - Tetris : 类似俄罗斯方块,模拟一下就好啦. #include<bits/stdc++.h> #define fi first #define se ...

  8. Educational Codeforces Round 41 (Rated for Div. 2) ABCDEF

    最近打的比较少...就只有这么点题解了. A. Tetris time limit per test 1 second memory limit per test 256 megabytes inpu ...

  9. Educational Codeforces Round 41 A B C D E

    A. Tetris 题意 俄罗斯方块,问能得多少分. 思路 即求最小值 Code #include <bits/stdc++.h> #define F(i, a, b) for (int ...

随机推荐

  1. 云开发 :云原生(Cloud Native)

    云开发 :云原生(Cloud Native) 云原生 所谓云原生,它不是一个产品,而是一套技术体系和一套方法论,用于构建和运行充分利用云计算模型优势的应用.云计算将提供无限制的按需计算能力和根据使用情 ...

  2. iOS底层框架浅析

    1.简介 IOS是由苹果公司为iPhone.iPod touch和iPad等设备开发的操作系统. 2.知识点 iPhone OS(现在叫iOS)是iPhone, iPod touch 和 iPad 设 ...

  3. Eclipse导war包忽略node_modules等文件

    window7环境下,选择project->Properties->如下图

  4. C++ 枚举定义

    我们在平常的编程中,时常需要为一些属性定义一组可以选择的值,比如文件打开的状态可能会有三种:输入 输出和追加 我们一般情况下记录这些状态是让每一个状态和一个常数相对应   比如 ; ; ; 这个方法虽 ...

  5. TCP/IP学习笔记9--以太网之基本概念1: 分类,连接方式

    时间是变化的财富.时钟模仿它,却只有变化而无财富. -- 泰戈尔 以太网(Ethernet)一词源于Ether(以太), 是介质的意思.在爱因斯坦哥们提出量子力学之前,人们普遍认为宇宙空间充满以太,并 ...

  6. LeetCode 278. 第一个错误的版本(First Bad Version)

    278. 第一个错误的版本 LeetCode278. First Bad Version 题目描述 你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每 ...

  7. TensorSpace:超酷炫3D神经网络可视化框架

    TensorSpace:超酷炫3D神经网络可视化框架 TensorSpace - 一款 3D 模型可视化框架,支持多种模型,帮助你可视化层间输出,更直观地展示模型的输入输出,帮助理解模型结构和输出方法 ...

  8. 037 Android Glide图片加载开源框架使用

    1.Glide简单介绍 Glide是一款由Bump Technologies开发的图片加载框架,使得我们可以在Android平台上以极度简单的方式加载和展示图片.Glide是一个快速高效的Androi ...

  9. python 并发的开端

    目录 网络并发 进程的基础 2.操作系统 操作系统的发展史 多道技术 第二代 1955~1965 磁带存储--批处理系统 第三代集成电路,多道程序系统(1955~1965) 进程的理论(重点) 2.操 ...

  10. python 之 前端开发( JavaScript变量、数据类型、内置对象、运算符、流程控制、函数)

    11.4 JavaScript 11.41 变量 1.声明变量的语法 // 1. 先声明后定义 var name; // 声明变量时无需指定类型,变量name可以接受任意类型 name= " ...