In this problem you will meet the simplified model of game Pudding Monsters.

An important process in developing any game is creating levels. A game field in Pudding Monsters is an n × n rectangular grid, n of its cells contain monsters and some other cells contain game objects. The gameplay is about moving the monsters around the field. When two monsters are touching each other, they glue together into a single big one (as they are from pudding, remember?).

Statistics showed that the most interesting maps appear if initially each row and each column contains exactly one monster and the rest of map specifics is set up by the correct positioning of the other game objects.

A technique that's widely used to make the development process more efficient is reusing the available resources. For example, if there is a large n × n map, you can choose in it a smaller k × k square part, containing exactly k monsters and suggest it as a simplified version of the original map.

You wonder how many ways there are to choose in the initial map a k × k (1 ≤ k ≤ n) square fragment, containing exactly k pudding monsters. Calculate this number.

Input

The first line contains a single integer n (1 ≤ n ≤ 3 × 105) — the size of the initial field.

Next n lines contain the coordinates of the cells initially containing monsters. The i-th of the next lines contains two numbers ri, ci(1 ≤ ri, ci ≤ n) — the row number and the column number of the cell that initially contains the i-th monster.

It is guaranteed that all ri are distinct numbers and all ci are distinct numbers.

Output

Print the number of distinct square fragments of the original field that can form a new map.

Examples
input
5
1 1
4 3
3 2
2 4
5 5
output
10

  题目大意 给定平面上有n个点,每行每列上只有一个点,问总共有多少个边长为k的矩形框住了k个点。

  刚开学,好久(也就两周)都没搞OI,差点不知OI为何物了。qaq。有人把这道题改题面拿给我们考试,然后考试时没想出正解,暴力分段90分。。于是班上出现了一群优秀的魔(膜)法师。

  显然,可以把它转化成序列上的问题(序列就是a[i]表示第i列上的点的纵坐标):有多少个长度为k的区间使得这一段的最大值和最小值之差等于k - 1。

  然后上CDQ分治进行瞎搞。记当前分治区间为[l, r],分治中心为mid,统计经过分治中心的子区间,分四种情况讨论:

  1)子区间的最大值和最小值同在左侧(相对于分治中心)

  2)子区间的最小值在左侧,最大值在右侧

  3)子区间的最大值和最小值同在右侧

  4)子区间的最大值在左侧,最小值在右侧

  由于情况1,3和2,4的做法类似,所以只考虑情况1,2

  情况1:

    记录左侧每个位置到分治中心的最大值和最小值。

    枚举子区间的左端点,可以根据记录的数据计算出右端点,如果合法(在分治中心右侧,并且最大值和最小值满足在左侧)就将答案加1.

  情况2:

    从分治中心向左枚举左端点i,考虑先使最值的条件合法。

    考虑到前后缀最大值和最小值都有不增或不减的单调性。所以设置两个"指针",r1和r2。

    r1是第一个使最大值在右侧的位置,r2是第一个使最小值不在左边的位置。那么左端点为i,右端点在整数区间[r1, r2)内的子区间都满足最值的限制。

    现在考虑如何统计答案。临时约定max[l, r]表示a[l],a[l + 1], ..., a[r]的最大值,同理定义min[l, r]。

    显然

    移一下项得到

    所以在挪动"指针"的时候把右边的一坨东东扔进某个桶里面就好了。挪动完成后根据当前枚举的左端点i,首先判断是否合法(比如什么r1大于等于r2的时候就continue就好了,如果合法的话就加上对应桶里的计数就好了。

    这种情况搞定了之后,不要忘记清空桶,由于桶可能很大,所以不要memset或者fill,for数组a就好了。

Code

 /**
* Codeforces
* Problem#526F
* Accepted
* Time: 140ms
* Memory: 8200k
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <bitset>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
#define clra(a) memset(a, false, sizeof(a))
const signed int inf = ((~0u) >> );
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
#define LL long long const int N = 3e5; int n;
int *arr;
int *pmin, *pmax, *rmin, *rmax;
int bucket[(N << ) + ]; inline void init() {
scanf("%d", &n);
arr = new int[(n + )];
pmin = new int[(n + )];
pmax = new int[(n + )];
rmin = new int[(n + )];
rmax = new int[(n + )];
for(int i = , x, y; i <= n; i++) {
scanf("%d%d", &x, &y);
arr[x] = y;
}
} LL CDQDividing(int l, int r) {
if(l == r) return ; int mid = (l + r) >> ;
LL rt = ;
pmin[mid] = arr[mid], pmax[mid] = arr[mid], rmin[mid + ] = arr[mid + ], rmax[mid + ] = arr[mid + ];
for(int i = mid - ; i >= l; i--)
pmin[i] = min(pmin[i + ], arr[i]), pmax[i] = max(pmax[i + ], arr[i]);
for(int i = mid + ; i <= r; i++)
rmin[i] = min(rmin[i - ], arr[i]), rmax[i] = max(rmax[i - ], arr[i]); for(int i = l, rg; i <= mid; i++) {
rg = i + pmax[i] - pmin[i];
rt += rg > mid && rg <= r && rmax[rg] < pmax[i] && rmin[rg] > pmin[i];
}
for(int i = mid + , lf; i <= r; i++) {
lf = i - rmax[i] + rmin[i];
rt += lf <= mid && lf >= l && pmax[lf] < rmax[i] && pmin[lf] > rmin[i];
}
for(int i = mid, r1 = mid + , r2 = mid + ; i >= l && r1 <= r; i--) { // The min num is on the left.
while(r2 <= r && rmin[r2] > pmin[i]) bucket[r2 - rmax[r2] + N]++, r2++;
while(r1 <= r && rmax[r1] < pmax[i]) bucket[r1 - rmax[r1] + N]--, r1++;
if(r1 < r2) rt += bucket[i - pmin[i] + N];
}
for(int i = mid + ; i <= r; i++)
bucket[i - rmax[i] + N] = ;
// cout << rt << endl;
for(int i = mid + , l1 = mid, l2 = mid; i <= r && l2 >= l; i++) { // The min num is on the right.
while(l1 >= l && pmin[l1] > rmin[i]) bucket[l1 + pmax[l1]]++, l1--;
while(l2 >= l && pmax[l2] < rmax[i]) bucket[l2 + pmax[l2]]--, l2--;
if(l1 < l2) rt += bucket[i + rmin[i]];
}
for(int i = l; i <= mid; i++)
bucket[i + pmax[i]] = ; return rt + CDQDividing(l, mid) + CDQDividing(mid + , r);
} inline void solve() {
printf(Auto, CDQDividing(, n));
} int main() {
init();
solve();
return ;
}

Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序的更多相关文章

  1. 【CF526F】Pudding Monsters cdq分治

    [CF526F]Pudding Monsters 题意:给你一个排列$p_i$,问你有对少个区间的值域段是连续的. $n\le 3\times 10^5$ 题解:bzoj3745 Norma 的弱化版 ...

  2. 奇袭 CodeForces 526F Pudding Monsters 题解

    考场上没有认真审题,没有看到该题目的特殊之处: 保证每一行和每一列都恰有一只军队,即每一个Xi和每一个Yi都是不一样 的. 于是无论如何也想不到复杂度小于$O(n^3)$的算法, 只好打一个二维前缀和 ...

  3. Codeforces 526F Pudding Monsters

    先把题目抽象一下: 有一个静态的数组,求有多少个区间[i,j]满足:j-i==max{ai,...,aj}-min{ai,...,aj} 也就是要求max-min+i-j==0的区间数 所以肿么做呢? ...

  4. Codeforces 1045G AI robots [CDQ分治]

    洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...

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

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

  6. CodeForces526F:Pudding Monsters (分治)

    In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...

  7. [Codeforce526F]:Pudding Monsters(分治)

    题目传送门 题目描述 由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试——魔界入侵.唯一一个神一般存在的Administrator被消灭了,靠原本的 ...

  8. Codeforces 436D - Pudding Monsters(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 这题数据范围有点迷惑啊--乍一看 \(\mathcal O(nm)\) 过不去,还以为是正解是 \(\mathcal O(n+m ...

  9. Codeforces 436D Pudding Monsters

    题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...

随机推荐

  1. Python使用suds调用webservice报错解决方法:AttributeError: 'Document' object has no attribute 'set'

    使用python的suds包调用webservice服务接口,报错:AttributeError: 'Document' object has no attribute 'set' 调用服务接口代码: ...

  2. Python对list列表及子列表进行排序

    python代码,对list进行升序排序,所有子列表也要进行排序 def iterList(listVar): listVar = sorted(listVar) for i,v in enumera ...

  3. PB中datewindow单双行显示不同颜色

    调出datewindow,找到detail中的列,右击properties,左侧Background中的color属性添加 IF(MOD(GETROW(),2)=0,RGB( 255, 250, 20 ...

  4. Git-什么是分支

    为了理解什么是分支,我们先要回顾Git是如何存储数据的. Git并不会保存文件的差异值或者说变化量,而是直接保存文件的快照. 在Git中提交时,会保存一个commit对象,该对象包含一个指向暂存内容快 ...

  5. <7>Cocos Creator 节点 cc.Node

    1.简介 节点(cc.Node)是渲染的必要组成部分.所有需要在游戏场景中显示的内容都必须是节点或者依附于节点之上.节点负责控制显示内容的位置.大小.旋转.缩放.颜色等信息. 2.节点属性 1: na ...

  6. 《大话设计模式》c++实现 抽象工厂模式

    为了更清晰地理解工厂方法模式,需要先引入两个概念: 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机.海信电视机.TCL电视机,则抽象电视机与具体品牌的电视机之间 ...

  7. github常见错误提示之一

    如果输入$ Git remote add origin git@github.com:Jomsou(github帐号名)/gitdemo(项目名).git 提示出错信息:fatal: remote o ...

  8. js原型链的说明

    首先需要明确的是:只有对象有__proto__属性,而函数只有prototype属性,没有__proto__属性,函数的原型有一个constructor属性,指向的是函数本身! Function是Ob ...

  9. Visible Lattice Points (莫比乌斯反演)

    Visible Lattice Points 题意 : 从(0,0,0)出发在(N,N,N)范围内有多少条不从重合的直线:我们只要求gcd(x,y,z) = 1; 的点有多少个就可以了: 比如 : 点 ...

  10. C# 自定义用户控件

    上篇:控件制作 本例是制作一个简单的自定义控件,然后用一个简单的测试程序,对于初学者来说,本例子比较简单,只能起到抛石引玉的效果.我也是在学习当中,今后会将自己所学的逐步写出来和大家交流共享. 第一步 ...