51nod-1555:布丁怪

来源:互联网 发布:多维分析 数据服务 编辑:程序博客网 时间:2024/05/16 19:07

1555 布丁怪
题目来源: CodeForces
基准时间限制:1.5 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
 收藏
 关注

布丁怪这一款游戏是在一个n×n 的矩形网格中进行的,里面有n个网格有布丁怪,其它的一些格子有一些其它的游戏对象。游戏的过程中是要在网格中移动这些怪物。如果两个怪物碰到了一起,那么他们就会变成一个更大的怪物。(谁叫他们是布丁呢?)

据统计,如果每一行每一列都只有一个布丁怪,那么这样的布局是比较吸引玩家的。

所以为了产生多种多样的有趣布局,我们会从一个 n×n 的有趣的地图中选取一个k×k (1≤k≤n)子矩形作为地图,而且这个子地图中恰好有k个布丁怪。

现在请你计算一下一个n×n 的有趣布局中,有多少种子地图是有趣的。


Input
单组测试数据。第一行有一个整数n (1≤n≤3×10^5),表示原始地图的大小。接下来n行,表示怪物的原始座标。第i行有两个整数ri,ci(1≤ri,ci≤n),表示第i个怪物所在的行和列。输入保证所有ri是不一样的,所有ci也是不一样的。
Output
输出一个整数,表示有多少种子地图是有趣的。
Input示例
样例输入151 14 33 22 45 5
Output示例
样例输出110


http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1555

分治:

对于区间[l, r]内所有的有趣块,可以分成三种

A:完全在[l, m)区间中

B:完全在[m+1, r]区间中

C:包含轴线m,其中m=(l+r)/2

对于前两种A和B,属于子问题求和即可,对于第三种C需要在分治时计算

那么如何计算?

可以将C再分为两种情况

①:有趣块中最左边的布丁怪和最右边的布丁怪都在同一侧,例如都在[l, m]区间中,或都在[m+1, r]区间中

②:有趣块中最左边的布丁怪和最右边的布丁怪不在同一侧

再对两种情况分别计算即可


#include<stdio.h>#include<algorithm>using namespace std;int a[300005], sum[300005], Min[300005], Max[300005];long long ans;void Div(int l, int r);int main(void){int n, i, x, y;scanf("%d", &n);for(i=1;i<=n;i++){scanf("%d%d", &x, &y);a[x] = y;}Div(1, n);printf("%lld\n", ans);return 0;}void Div(int l, int r){int m, i, L, R, now;m = (l+r)/2;if(l>r)return;Max[m+1] = Min[m+1] = a[m+1];Max[m] = Min[m] = a[m];for(i=m+2;i<=r;i++)Max[i] = max(Max[i-1], a[i]), Min[i] = min(Min[i-1], a[i]);for(i=m-1;i>=l;i--)Max[i] = max(Max[i+1], a[i]), Min[i] = min(Min[i+1], a[i]);/*********************************************************************************/for(i=m+1;i<=r;i++)//情况①{now = i-Max[i]+Min[i];//now是有趣块下边界,i是上边界,下面同理if(now<=m && now>=l && Min[now]>Min[i] && Max[now]<Max[i])ans++;}for(i=m;i>=l;i--){now = i-Min[i]+Max[i];if(now>=m && now<=r && Min[now]>=Min[i] && Max[now]<=Max[i])ans++;}/*********************************************************************************/L = R = m+1;//情况②for(i=m;i>=l;i--)//最左边的布丁怪在区间[1,m]中{while(R<=r && Min[R]>Min[i])sum[Max[R]-R+m]++, R++;while(L<R && Max[L]<Max[i])sum[Max[L]-L+m]--, L++;ans += sum[Min[i]+m-i];}while(L<R)sum[Max[L]-L+m]--, L++;//初始化sum数组,不能用memsetL = R = m;for(i=m+1;i<=r;i++)//最左边的布丁怪在区间[m+1, r]中{while(R>=l && Min[R]>Min[i])sum[Max[R]+R-m]++, R--;while(L>R && Max[L]<Max[i])sum[Max[L]+L-m]--, L--;ans += sum[Min[i]-m+i];}while(L>R)sum[Max[L]+L-m]--, L--;Div(l, m-1);Div(m+1, r);}


1 0