矩形Rectangle

题目

 

矩形Rectangle_第1张图片

 我怎么这么菜啊

思路&题解

自己的思路

以为可以用扫描线扫,但是发现这些点不连续,没有多想,就去看题解了

正解

首先扫描线扫坐标,先确定右端线,然后在从右往左确定左端的线,边扫边加点,那么矩形左右已经确定了,现在考虑左端线:

矩形Rectangle_第2张图片

左端线上的一个点,它的贡献就为左端点上面的点 与左端点下面的点构成的矩形,但是对于上界在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;
}

 

你可能感兴趣的:(总结,扫描线,树状数组)