矩形Rectangle

BIT_jzx發表於2020-10-11

題目

 

 我怎麼這麼菜啊

思路&題解

自己的思路

以為可以用掃描線掃,但是發現這些點不連續,沒有多想,就去看題解了

正解

首先掃描線掃座標,先確定右端線,然後在從右往左確定左端的線,邊掃邊加點,那麼矩形左右已經確定了,現在考慮左端線:

左端線上的一個點,它的貢獻就為左端點上面的點 與左端點下面的點構成的矩形,但是對於上界在l點以內的點與下界在r以內的點的矩形並不是最小矩形,要減去,其中點l是在右端線上第一個比i大於或等於的,r是右端線上最後一個比i小的,由於是區間,就可以用樹狀陣列維護一下,然後計算即可

但是這裡還要判斷一下左端線上i下面是否還有點,如果有,那麼下界一定是不能到那個點的,記得判斷

 

程式碼

#include<bits/stdc++.h>
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;
}

 

相關文章