以为可以用扫描线扫,但是发现这些点不连续,没有多想,就去看题解了
首先扫描线扫坐标,先确定右端线,然后在从右往左确定左端的线,边扫边加点,那么矩形左右已经确定了,现在考虑左端线:
左端线上的一个点,它的贡献就为左端点上面的点 与左端点下面的点构成的矩形,但是对于上界在l点以内的点与下界在r以内的点的矩形并不是最小矩形,要减去,其中点l是在右端线上第一个比i大于或等于的,r是右端线上最后一个比i小的,由于是区间,就可以用树状数组维护一下,然后计算即可
但是这里还要判断一下左端线上i下面是否还有点,如果有,那么下界一定是不能到那个点的,记得判断
#include
using namespace std;
#define ll long long
const int MAXN = 1e4 + 3;
const ll mod = 1e9 + 7;
int n;
ll ans;
struct node{
int x , y;
friend bool operator < ( node a , node b ){
if( a.x ^ b.x ) return a.x < b.x;
return a.y > b.y;
}
}a[MAXN];
bool f[MAXN];
struct tree{
ll num , x;
}tre[2504];
int maxx;
void modify( int x , ll delta , ll num ){
if( f[x] ) return ;
int y = x;
for( ; x <= 2500 ; x += ( x & -x ) )
tre[x].num += num , tre[x].x += delta;
f[y] = 1;
}
tree query( int x ){
tree ans;ans.x = ans.num= 0;
for( ; x ; x -= ( x & -x) )
ans.x += tre[x].x , ans.num += tre[x].num;
return ans;
}
void pre( int x ){
f[x] = 0;
for( ; x <= 2500 ; x += ( x & -x ) )
tre[x].num =0 , tre[x].x = 0;
}
bool flag[2504];
int b[MAXN] , blen , clen , c[MAXN];
int main(){
scanf( "%d" , &n );
for( int i = 1 ; i <= n ; i ++ )
scanf( "%lld%lld" , &a[i].x , &a[i].y ) , maxx = max( a[i].y , maxx ) , flag[a[i].x] = 1;
sort( a + 1 , a + n + 1 );
for( int i = a[n].x ; i >= a[1].x ; i -- ){
if( !flag[i] ) continue;
blen = clen = 0;
int last = 0;
for( int j = n ; j >= 1 ; j -- ){
if( a[j].x > i ) continue;
if( a[j].x == i ){
b[++blen] = a[j].y;
modify( a[j].y , a[j].y , 1 );
}
else if( a[j].x != last && last ){
b[blen+1] = 2501;
for( int k = 1 ; k <= clen ; k ++ ){
tree s = query( 2501 ) , s1 = query( c[k] - 1 );
s.num -=s1.num , s.x -= s1.x;
tree s2 = query( c[k-1] );s1 = query( c[k] );
s1.num -= s2.num , s1.x -= s2.x;
ans = ( ans + (s1.num * s.x % mod - s.num * s1.x % mod + mod ) % mod * 1ll * ( i - last ) % mod ) % mod;
int o = lower_bound( b + 1 , b + blen + 2 , c[k] ) - b , o1 = o - 1;
s = query( b[o] - 1 ) , s1 = query( c[k] - 1 );
s.num -= s1.num , s.x -= s1.x;
if( b[o1] >= c[k-1] )
s1 = query( c[k] ) , s2 = query( b[o1] ) ;
else
s1 = query( c[k] ) , s2 = query( c[k-1] ) ;
s1.num -= s2.num , s1.x -= s2.x;
ans = ( ans - ((s1.num * s.x % mod - s.num * s1.x % mod + mod ) % mod * 1ll * ( i - last) % mod) + mod ) % mod;
}
//printf( "%lld\n" , ans );
clen = 0;
c[++clen] = a[j].y;
modify( a[j].y , a[j].y , 1 );
last = a[j].x;
}
else{
c[++clen] = a[j].y;
modify( a[j].y , a[j].y , 1 );
last = a[j].x;
}
}
b[blen+1] = 2501;
for( int k = 1 ; k <= clen ; k ++ ){
tree s = query( 2501 ) , s1 = query( c[k] - 1 );
s.num -=s1.num , s.x -= s1.x;
tree s2 = query( c[k-1] );s1 = query( c[k] );
s1.num -= s2.num , s1.x -= s2.x;
ans = ( ans + (s1.num * s.x % mod - s.num * s1.x % mod + mod ) % mod * 1ll * ( i - last ) % mod ) % mod;
int o = lower_bound( b + 1 , b + blen + 2 , c[k] ) - b , o1 = o - 1;
s = query( b[o] - 1 ) , s1 = query( c[k] - 1 );
s.num -= s1.num , s.x -= s1.x;
if( b[o1] >= c[k-1] )
s1 = query( c[k] ) , s2 = query( b[o1] ) ;
else
s1 = query( c[k] ) , s2 = query( c[k-1] ) ;
s1.num -= s2.num , s1.x -= s2.x;
ans = ( ans - ((s1.num * s.x % mod - s.num * s1.x % mod + mod ) % mod * 1ll * ( i - last) % mod) + mod ) % mod;
}
//printf( "%lld\n" , ans );
for( int j = 1 ; j <= n ; j ++ )
pre( a[j].y );
}
printf( "%lld\n" , ans );
return 0;
}