Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序
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.
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.
Print the number of distinct square fragments of the original field that can form a new map.
5
1 1
4 3
3 2
2 4
5 5
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分治 - 桶排序的更多相关文章
- 【CF526F】Pudding Monsters cdq分治
[CF526F]Pudding Monsters 题意:给你一个排列$p_i$,问你有对少个区间的值域段是连续的. $n\le 3\times 10^5$ 题解:bzoj3745 Norma 的弱化版 ...
- 奇袭 CodeForces 526F Pudding Monsters 题解
考场上没有认真审题,没有看到该题目的特殊之处: 保证每一行和每一列都恰有一只军队,即每一个Xi和每一个Yi都是不一样 的. 于是无论如何也想不到复杂度小于$O(n^3)$的算法, 只好打一个二维前缀和 ...
- Codeforces 526F Pudding Monsters
先把题目抽象一下: 有一个静态的数组,求有多少个区间[i,j]满足:j-i==max{ai,...,aj}-min{ai,...,aj} 也就是要求max-min+i-j==0的区间数 所以肿么做呢? ...
- Codeforces 1045G AI robots [CDQ分治]
洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...
- Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]
洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...
- CodeForces526F:Pudding Monsters (分治)
In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...
- [Codeforce526F]:Pudding Monsters(分治)
题目传送门 题目描述 由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试——魔界入侵.唯一一个神一般存在的Administrator被消灭了,靠原本的 ...
- Codeforces 436D - Pudding Monsters(dp)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 这题数据范围有点迷惑啊--乍一看 \(\mathcal O(nm)\) 过不去,还以为是正解是 \(\mathcal O(n+m ...
- Codeforces 436D Pudding Monsters
题意简述 开始有无限长的一段格子,有n个格子种有布丁怪兽,一开始连续的布丁怪兽算一个布丁怪兽. 每回合你可以将一个布丁怪兽向左或右移动,他会在碰到第一个布丁怪兽时停下,并与其合并. 有m个特殊格子,询 ...
随机推荐
- Xception网络结构理解
Xception网络是由inception结构加上depthwise separable convlution,再加上残差网络结构改进而来/ 常规卷积是直接通过一个卷积核把空间信息和通道信息直接提取出 ...
- json_decode 转数组
json_decode($json); 直接转义json数据后会发现转义后的数据时对象类型, 想要获得数组型,加一个参数 json_decode($json,true);
- keepalived+双主架构
简介 keepalived是基于VRRP协议的,全称 Virtual Redundent Routing Protocal 虚拟路由协议,为解决静态路由单点故障引起的网络失效问题设计的一套主备协议 两 ...
- unity之UI
1.Vector3坐标 2.地球,月球,太阳的旋转关系 using System.Collections; using System.Collections.Generic; using UnityE ...
- CRUD简单查询
一.查询所有数据 select * from car 二.查询指定列 select code , price from car 三.修改查询出的列名 select code as '代号' , nam ...
- Unity shader学习之标准的Unity shader
包含光照,可处理多个光源,有光照衰减和阴影的shader,代码如下: 转载请注明出处:http://www.cnblogs.com/jietian331/p/7199311.html Shader & ...
- windows8安装msi或exe软件提示2503错误的解决办法
windows8以后的版本安装msi软件(比如nodejs.msi.Git.msi.python.msi.T ortoiseSVN.msi)的时候老师出现2503.2502的错误,究其原因还是系统权限 ...
- python 试题归纳及答疑 更新中.....
一.Python基础篇(80题) 1.你为什么学习Python? 一.答题思路 1.阐述 python 优缺点 2.Python应用领域说明 3.根据自身工作情况阐述为什么会使用python 1)py ...
- timestamp与timedelta,管理信息系统概念与基础
1.将字符串‘2017年10月9日星期一9时10分0秒 UTC+8:00’转换为timestamp. 2.100天前是几号? 今年还有多少天? #timestamp与timedelta from ...
- verilog代码基础
verilog拼接符用法: https://zhidao.baidu.com/question/531343285.html wire [31:0] bit_mask = { {8{be[3]}}, ...