##Description
由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上要迎来最终的压力测试——魔界入侵。
唯一一个神一般存在的Administrator被消灭了,靠原本的整合骑士的力量是远远不够的。所以爱丽丝动员了UW全体人民,与整合骑士一起抗击魔族。
在UW的驻地可以隐约看见魔族队伍的大本营。整合骑士们打算在魔族入侵前发动一次奇袭,袭击魔族大本营!
为了降低风险,爱丽丝找到了你,一名优秀斥候,希望你能在奇袭前对魔族大本营进行侦查,并计算出袭击的难度。
经过侦查,你绘制出了魔族大本营的地图,然后发现,魔族大本营是一个N×N的网格图,一共有N支队伍驻扎在一些网格中(不会有两只队伍驻扎在一起)。
在大本营中,每有一个k×k(1≤k≤N)的子网格图包含恰好k支队伍,我们袭击的难度就会增加1点。
现在请你根据绘制出的地图,告诉爱丽丝这次的袭击行动难度有多大。
##Solution
一开始还以为是什么树套树什么的,结果打了个暴力,就不管了。
####转化为序列上的问题
因为每行每列都 只会出现一个点,b[x][y]有点,那么a[x]=y。
一个k*k的正方形里面有一个点,就相当于一个长度为k的区间中最大值-最小值=k-1就合法。
####怎么做——分治
线段树没有想出来n log n的方法。
想一想经典的方法,ans[l,r]=ans[l,mid-1]+ans[mid+1,r]+跨区间的答案。
问题就是跨区间的答案要怎么算。
####跨区间怎么算
因为要跨区间,那么符合答案的一段区间的[l1,r1],l1∈[l,mid],r1∈[mid+1,r]
有四种情况:
1、最小值在左边,最大值在左边。
2、最小值在右边,最大值在右边。
3。最小值在左边,最大值在右边。
4、最小值在右边,最大值在左边。
这里只讨论情况1和情况3,因为情况2和4与1和3对称。
先处理两个数组,da[i],xiao[i]。因为要跨区间,所以如果区间的左端点是i∈[l,mid],那么最大值值在[i,mid]区间内的,所以da[i]在[l,mid]的值是【NOIP提高】奇袭_分治的最大值;如果要在[mid+1,r]区间,那么da[i]的值是【NOIP提高】奇袭_分治_02的最大值。
xiao[i]同理。
情况1:最小值在左边,最大值在左边。
枚举一个左端点j,假设有一个右端点i,因为最值在左边,那么满足i-j=da[j]-xiao[j],所以j可以算出来i=j+(da[j]-xiao[j]),那么只要满足左边的最小值<右边的最小值,左边的最大值>右边的最大值就好了(即da[j]>=da[i]&&xiao[j]<=xiao[i)。
情况3:最小值在左边,最大值在右边。
枚举一个左端点i,如果有一个右端点j,因为最小值在左边,最大值在右边,所以满足左边的最小值<右边的最小值,左边的最大值<右边的最大值。那么左端点固定,右端点就会有一段可行范围。
可行区间还要满足j-i=da[j]-xiao[i],转化一下变成j-da[j]=i-xiao[i],所以把所有在可行区间的j,用一个桶tong[j-da[j]]++,那么每次答案加上tong[i-xiao[i]]就好了,i-da[j]可能会变成负数,所以需要加上mid变成tong[i-xiao[i]+mid]。
枚举可行区间不用从头枚举如果i为左端点的可行区间是l[i],r[i],那么l[i+1]>=l[i],r[i+1]>=r[i],因为da[i]和xiao[i]满足单调性。
##Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=500007;
int i,j,k,l,t,n,m;
long long ans;
int a[maxn],da[maxn],xiao[maxn],tong[maxn];
void solve(int l,int r){
if(l>r)return;
int mid=(l+r)/2,i,j,k,t;
da[mid]=xiao[mid]=a[mid];
da[mid+1]=xiao[mid+1]=a[mid+1];
fod(i,mid-1,l)da[i]=max(da[i+1],a[i]),xiao[i]=min(xiao[i+1],a[i]);
fo(i,mid+2,r)da[i]=max(da[i-1],a[i]),xiao[i]=min(xiao[i-1],a[i]);
fod(j,mid,l){
i=j+(da[j]-xiao[j]);
if(i>=mid&&i<=r&&da[j]>=da[i]&&xiao[j]<=xiao[i])ans++;
}
fo(i,mid+1,r){
j=i-(da[i]-xiao[i]);
if(j<=mid&&j>=l&&da[j]<=da[i]&&xiao[j]>=xiao[i])ans++;
}
k=t=mid+1;
fod(i,mid,l){
while(t<=r&&xiao[t]>=xiao[i])tong[da[t]-t+mid]++,t++;
while(k<t&&da[k]<=da[i])tong[da[k]-k+mid]--,k++;
ans+=tong[xiao[i]-i+mid];
}
fo(i,k,t-1)tong[da[i]-i+mid]--;
k=t=mid;
fo(i,mid+1,r){
while(k>=l&&xiao[k]>=xiao[i])tong[da[k]+k-mid]++,k--;
while(t>k&&da[t]<=da[i])tong[da[t]+t-mid]--,t--;
ans+=tong[xiao[i]+i-mid];
}
fo(i,k+1,t)tong[da[i]+i-mid]--;
solve(l,mid-1),solve(mid+1,r);
}
int main(){
// freopen("fan.in","r",stdin);
scanf("%d",&n);
fo(i,1,n){
scanf("%d%d",&k,&l);
a[k]=l;
}
solve(1,n);
printf("%I64d\n",ans);
}