Live2d Test Env

CodeForces526F:Pudding Monsters (分治)

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*N的棋盘,以及N个棋子放置情况,保证每一行,每一列只有一个棋子。问现在有多少个子正方形,满足每一行每一列都有一个棋子。

思路:以x坐标为第一关键字,转化为一维数组,如样例(1,4,2,3,5),然后问题就成了有多少个练习子区间[i,j],满足i-j=max-min,棋子max和min是区间最大和最小值。 显然分治可以搞,问题转化为多个子问题:求跨过Mid的区间,满足i-j=max-min。

如何线性地解决子问题:由于max和min都是单调的,我们枚举i或者j,然后验证另外一个是否在当前子区间区间里,同时满足max和min的关系,累加答案。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=3e5+10;
int mx[maxn],mn[maxn],sum[maxn<<1];
int a[maxn],N; ll ans;
void solve(int L,int R)
{
    if(L==R){ ans++; return ;}
    int Mid=(L+R)/2;
    solve(L,Mid); solve(Mid+1,R);
    mx[Mid]=mn[Mid]=a[Mid]; mx[Mid+1]=mn[Mid+1]=a[Mid+1];
    for(int i=Mid-1;i>=L;i--) mx[i]=max(mx[i+1],a[i]);//预处理 
    for(int i=Mid-1;i>=L;i--) mn[i]=min(mn[i+1],a[i]);
    for(int i=Mid+2;i<=R;i++) mx[i]=max(mx[i-1],a[i]);
    for(int i=Mid+2;i<=R;i++) mn[i]=min(mn[i-1],a[i]);
    
    for(int i=Mid;i>=L;i--){   //都在左测 
        int j=mx[i]-mn[i]+i;
        if(j<=R&&j>Mid&&mx[j]<mx[i]&&mn[j]>mn[i]) ans++;
    }
    for(int i=Mid+1;i<=R;i++){  //都在右侧 
        int j=i-mx[i]+mn[i];
        if(j<=Mid&&j>=L&&mx[j]<mx[i]&&mn[j]>mn[i]) ans++;
    }
    int j=Mid+1,k=Mid+1;
    for(int i=Mid;i>=L;i--){ //左小右大 
        while(j<=R&&mn[j]>mn[i]) sum[mx[j]-j+N]++,j++;
        while(k< j&&mx[k]<mx[i]) sum[mx[k]-k+N]--,k++;
        ans+=(ll)sum[mn[i]-i+N];
    }
    while(k<j) sum[mx[k]-k+N]--,k++;
    j=Mid,k=Mid;
    for(int i=Mid+1;i<=R;i++){ //左大右小 
        while(j>=L&&mn[j]>mn[i]) sum[mx[j]+j]++,j--;
        while(k> j&&mx[k]<mx[i]) sum[mx[k]+k]--,k--;
        ans+=(ll)sum[mn[i]+i];
    }
    while(k>j) sum[mx[k]+k]--,k--;
}
int main()
{
    int x,y,i,j;
    scanf("%d",&N);
    for(i=1;i<=N;i++) scanf("%d%d",&x,&y) ,a[x]=y;
    solve(1,N);
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-05-28 14:52  nimphy  阅读(467)  评论(0编辑  收藏  举报