JZOJ5006. A

来源:互联网 发布:滨州大数据产业园 编辑:程序博客网 时间:2024/06/05 16:07

题目大意

给出一个长度为N,宽度为1,高度无限的水箱,有N1个挡板将其分为N1×1×的小格,然后向每个小格中注水。
现在有M个条件,每个条件描述一个格子有水或者没水。
问最多能同时满足多少个条件。

Data Constraint
n,m100000

题解

如果我们能将这些区域的关系建成一棵树的话,就很好求答案了。
考虑扫描线,从下往上扫描,每次遇到一个挡板,就合并板两侧的区域,作为一个新区域,这个可以并查集维护。然后将条件挂到对应区域的点上即可。

时间复杂度:O(Nα(N))

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 5000000 + 10struct Note {    int w , h , type ;} C[N] ;struct Stype {    int Num0 , Num1 ;} P[N] ;int Node[2*N] , Next[2*N] , Head[N] , tot ;int f[N] , g[N] , fa[N] ;int Case , n , m , Cnt ;bool cmp( Note a , Note b ) { return a.h < b.h || ( a.h == b.h && a.type < b.type ) || ( a.h == b.h && a.type == b.type && a.w < b.w ) ; }int Read() {    int ret = 0 ;    char ch = getchar() ;    while ( ch < '0' || ch > '9' ) ch = getchar() ;    while ( ch >= '0' && ch <= '9' ) {        ret = ret * 10 + ch - '0' ;        ch = getchar() ;    }    return ret ;}void link( int u , int v ) {    Node[++tot] = v ;    Next[tot] = Head[u] ;    Head[u] = tot ;}int Get( int x ) { return fa[x] == x ? x : fa[x] = Get( fa[x] ) ; }int NewNode() {    ++ Cnt ;    fa[Cnt] = Cnt ;    P[Cnt].Num0 = P[Cnt].Num1 = 0 ;    return Cnt ;}void Union( int x , int y ) {    int fy = Get(y) ;    if ( fy == x ) return ;    link( x , fy ) ;    fa[fy] = x ;}void DFS( int x ) {    f[x] = P[x].Num1 ;    g[x] = P[x].Num0 ;    for (int p = Head[x] ; p ; p = Next[p] ) {        DFS( Node[p] ) ;        f[x] += f[Node[p]] ;        g[x] += max( f[Node[p]] , g[Node[p]] ) ;    }}int main() {    Case = Read() ;    while ( Case -- ) {        tot = Cnt = 0 ;        memset( P , 0 , sizeof(P) ) ;        memset( Head , 0 , sizeof(Head) ) ;        n = Read() , m = Read() ;        for (int i = 1 ; i <= n ; i ++ ) fa[i] = i ;        for (int i = 1 ; i < n ; i ++ ) {            C[m+i].w = i ;            C[m+i].h = Read() ;            C[m+i].h ++ ;            C[m+i].type = -1 ;        }        for (int i = 1 ; i <= m ; i ++ ) {            C[i].w = Read() ;            C[i].h = Read() ;            C[i].type = Read() ;            C[i].h ++ ;        }        sort( C + 1 , C + n + m , cmp ) ;        Cnt = n ;        C[n+m].h = -1 ;        for (int i = 1 ; i <= n + m - 1 ; i ++ ) {            for (int j = i ; j <= n + m ; j ++ ) {                if ( C[j].h != C[i].h ) {                    i = j - 1 ;                    break ;                }                if ( C[j].type == -1 ) {                    int now = NewNode() ;                    Union( now , C[j].w ) ;                    Union( now , C[j].w + 1 ) ;                } else {                    int now = NewNode() ;                    Union( now , C[j].w ) ;                    if ( C[j].type == 0 ) P[now].Num0 ++ ;                    else P[now].Num1 ++ ;                }            }        }        int Root = Get(1) ;        DFS( Root ) ;        printf( "%d\n" , max( f[Root] , g[Root] ) ) ;    }    return 0 ;}

以上.

1 0
原创粉丝点击