题目大意
给出一个长度为
N
,宽度为1,高度无限的水箱,有
现在有
M
个条件,每个条件描述一个格子有水或者没水。
问最多能同时满足多少个条件。
Data Constraint
题解
如果我们能将这些区域的关系建成一棵树的话,就很好求答案了。
考虑扫描线,从下往上扫描,每次遇到一个挡板,就合并板两侧的区域,作为一个新区域,这个可以并查集维护。然后将条件挂到对应区域的点上即可。
时间复杂度: O(Nα(N))
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 5000000 + 10
struct 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 ;
}
以上.