Description
农夫约翰有一块很大的田,他正在考虑种甜玉米。经过对他农田的调查,FJ发现它形成了一个(N-1)×(N-1)的
正方形。西南角为坐标(0,0),东北角是(N-1,N-1)。在某些整数坐标的位置中有双头喷头,每一个都能够同
时喷洒水和肥料。一个在(i,j)处的双头喷头会将水洒在农田中所有在其东面且在其北面的区域,将肥料洒在农
田中所有在其南面且在其西面的区域。形式化地说,这个喷头将会将水洒在所有满足N≥x≥i和N≥y≥j的实数坐标
(x,y)上,会将肥料洒在所有满足0≤x≤i和0≤y≤j的实数坐标上农民约翰想在一些边与坐标轴平行的长方形农田
里种植甜玉米。然而,为了甜玉米的生长,矩形内的所有点都必须由双头喷头浇水和施肥。当然,矩形必须有正的
面积,否则农民约翰就不能在里面种植任何玉米!帮助农民约翰确定可以种植甜玉米的拥有正面积的矩形农田数。
由于这个数字可能很大,所以输出对为10^9 + 7取模
Input
第一行包含一个整数N,表示农场的大小(1≤N≤10^5)。
接下来的n行各包含两个由空格分隔的整数。这些整数中0≤i,j≤N-1,这表示有一个双头喷头位于(i,j)的位置。
保证每列都有一台喷头,每排正好有一台喷头。这也就是说,没有两个喷头有相同的x坐标或y坐标。
Output
输出包含一行,表示拥有正面积的合法矩形农田的个数,对10^9+7取模.
Sample Input
5
0 4
1 1
2 2
3 0
4 3
Sample Output
21
题解
比赛的最后半小时想到50分做法然而并没有细想就这么放过了式子题..
预处理能种小麦的点,发现总是组成一个多边形
这个多边形一定是阶梯状的…..画个图就清楚了就一些矩阵面积并
我们把答案的式子写出来
∑i=0n−1∑j=lw[i]up[i]∑k=lw[i]j−1i−lk ∑ i = 0 n − 1 ∑ j = l w [ i ] u p [ i ] ∑ k = l w [ i ] j − 1 i − l k
其中up[i]表示第i列向上能到达的最高行,lw[i]表示向下能到达的最低行, lk l k 表示第k行向左最多能去到哪一列
画图最清晰了
一通乱化
∑i=0n−1∑j=lw[i]up[i]i∗(j−lw[i])−∑k=lw[i]j−1lk ∑ i = 0 n − 1 ∑ j = l w [ i ] u p [ i ] i ∗ ( j − l w [ i ] ) − ∑ k = l w [ i ] j − 1 l k
∑i=0n−1i∗(1+up[i]−lw[i])∗(up[i]+lw[i])2−∑j=lw[i]+1up[i]∑k=lw[i]j−1lk ∑ i = 0 n − 1 i ∗ ( 1 + u p [ i ] − l w [ i ] ) ∗ ( u p [ i ] + l w [ i ] ) 2 − ∑ j = l w [ i ] + 1 u p [ i ] ∑ k = l w [ i ] j − 1 l k
化到这个地方前面的式子已经可以 O(1) O ( 1 ) 计算了,下来主要化后面的式子
设S[i]表示l数组的前缀和,pre[i]表示S数组的前缀和
有
∑j=lw[i]+1up[i]Sj−1−Slw[i]−1 ∑ j = l w [ i ] + 1 u p [ i ] S j − 1 − S l w [ i ] − 1
preup[i]−1−prelw[i]−1−Slw[i]−1∗(up[i]−lw[i]) p r e u p [ i ] − 1 − p r e l w [ i ] − 1 − S l w [ i ] − 1 ∗ ( u p [ i ] − l w [ i ] )
组合起来即为
∑i=0n−1i∗(1+up[i]−lw[i])∗(up[i]+lw[i])2−(preup[i]−1−prelw[i]−1−Slw[i]−1∗(up[i]−lw[i])) ∑ i = 0 n − 1 i ∗ ( 1 + u p [ i ] − l w [ i ] ) ∗ ( u p [ i ] + l w [ i ] ) 2 − ( p r e u p [ i ] − 1 − p r e l w [ i ] − 1 − S l w [ i ] − 1 ∗ ( u p [ i ] − l w [ i ] ) )
于是 O(n) O ( n ) 扫一遍就出答案了..
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct matrix{int x,y;}a[1000005];
bool cmp(matrix n1,matrix n2){return n1.x<n2.x;}
const LL mod=1e9+7;
LL pow_mod(LL a,int b)
{
LL ret=1;
while(b)
{
if(b&1)ret=ret*a%mod;
a=a*a%mod;b>>=1;
}
return ret;
}
int n;
LL lw[1000005],up[1000005],L[1000005];
LL S[1000005],pre[1000005];
int main()
{
n=read();
for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
sort(a+1,a+1+n,cmp);
memset(up,-1,sizeof(up));
memset(lw,-1,sizeof(lw));
memset(L,-1,sizeof(L));
up[a[n].x]=a[n].y;int mx=a[n].y;
for(int i=n-1;i>=1;i--)
if(mx<a[i].y)
{
up[a[i].x+1]=mx;up[a[i].x]=a[i].y;
mx=a[i].y;
}
for(int i=n-1;i>=0;i--)if(up[i]==-1)up[i]=up[i+1];
lw[a[1].x]=a[1].y;int mn=a[1].y;
L[a[1].y]=a[1].x;int last=a[1].x;
for(int i=2;i<=n;i++)
if(mn>a[i].y)
{
L[a[i].y]=a[i].x;
lw[a[i].x-1]=mn;lw[a[i].x]=a[i].y;
mn=a[i].y;last=a[i].x;
}
for(int i=0;i<n;i++)if(lw[i]==-1)lw[i]=lw[i-1];
for(int i=0;i<n;i++)if(L[i]==-1)L[i]=L[i-1];
// printf("%d\n",L[546]);
/* for(int i=0;i<n;i++)printf("%d ",up[i]);
puts("");
for(int i=0;i<n;i++)printf("%d ",lw[i]);
puts("");
for(int i=0;i<n;i++)printf("%d ",L[i]);
puts("");*/
//init
for(int i=0;i<n;i++)S[i]=(S[i-1]+L[i])%mod;
for(int i=0;i<n;i++)pre[i]=(pre[i-1]+S[i])%mod;
LL ans=0;
for(int i=0;i<n;i++)
{
LL cnt=(LL)((i*(up[i]-lw[i]+1))*(up[i]-lw[i])/2)%mod;
LL tmp=pre[up[i]-1]-pre[lw[i]-1]-S[lw[i]-1]*(up[i]-lw[i])%mod;
while(tmp<0)tmp+=mod;
ans=(ans+cnt-tmp);
while(ans<0)ans+=mod;
ans%=mod;
}
printf("%lld\n",ans);
return 0;
}