纯容斥定理:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> #include<string> #define LL long long using namespace std; const int INF = 10000; class Node { public: int x1,y1,x2,y2; }node[24]; int status[1250000],N; void DFS( int x1 , int y1 , int x2 , int y2 , int deep , int sign, int sta ) { if( x1 >= x2 || y1 >= y2 ) return; if( deep == N ) { if( sta !=0 ) for( int i = 1 ; i < 1 << N; i ++ ) { if( (i | sta) <= i ) status[i] += sign*( x2 - x1 ) * ( y2 - y1 ); } return ; } DFS( x1 , y1 , x2 , y2 , deep + 1, sign , sta ); DFS(max(x1,node[deep].x1),max(y1,node[deep].y1),min(x2,node[deep].x2),min(y2,node[deep].y2),deep+1,-sign,sta|(1<<deep)); } int main( ) { int M,num,n,Case = 1; while( scanf( "%d%d",&N,&M ),N|M ) { memset( status , 0 , sizeof( status ) ); for( int i = 0 ; i < N ; i ++ ) scanf( "%d%d%d%d",&node[i].x1,&node[i].y1,&node[i].x2,&node[i].y2 ); DFS( 0 , 0 , INF , INF , 0 , -1 ,0 ); printf( "Case %d:\n",Case++ ); for( int i = 1 ; i <= M ; i ++ ) { int sta = 0; scanf( "%d",&n ); for( int j = 0 ; j < n ; j ++ ) { scanf( "%d",&num ); sta |= 1<< (num-1); } printf( "Query %d: %d\n",i,status[sta] ); } puts( "" ); } //system( "pause" ); return 0; }
优化版:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> #include<string> #define LL long long using namespace std; class Node { public: int x1,y1,x2,y2; }node[24]; int status[1100000],sta[100024],N,M; const int INF = 1000; void DFS( int x1,int y1,int x2,int y2 ,int deep, int s,int sign ) { if( x1>=x2 || y1 >= y2 ) return; if( deep == N ) { if( s!=0 ) { for( int i = 0; i < M; i ++ ) { if( (sta[i] | s) <= sta[i] ) { status[sta[i]] += sign*( x2 - x1 )*( y2 - y1 ); } } } return; } DFS( x1 , y1 , x2 , y2 , deep+1, s , sign ); DFS(max(x1,node[deep].x1),max(y1,node[deep].y1),min(x2,node[deep].x2),min(y2,node[deep].y2),deep+1,s|(1<<deep),-sign); } int main( ) { int n,num,Case=1; while( scanf("%d%d",&N,&M),N||M ) { for( int i = 0 ; i < N ; i++ ) { scanf( "%d%d%d%d",&node[i].x1,&node[i].y1,&node[i].x2,&node[i].y2); } memset( status, 0 , sizeof( status ) ); memset( sta, 0 , sizeof( sta ) ); for( int i = 0 ; i < M ;i ++ ) { scanf( "%d",&n ); for( int j = 0 ; j < n ; j ++ ) { scanf( "%d",&num ); sta[i] |=1<<(num-1); } } DFS( 0,0,INF,INF,0,0,-1 ); printf( "Case %d:\n",Case++ ); for( int i = 0 ; i < M; i ++ ) { printf( "Query %d: %d\n",i+1,status[sta[i]] ); } puts(""); } //system( "pause" ); return 0; }
用离散化处理:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> #include<string> #define LL long long using namespace std; class Rec { public: int x1,y1,x2,y2; }rec[24],p[24]; int N,M; bool cmp1( Rec a, Rec b ) { return a.y1 < b.y1; } bool cmp2( int a, int b ) { return a < b; } void Solve( ){ int num,n,cnt,left[50],right[50],tx[50],count,t; for( int k = 1 ; k <= M; k ++ ) { t = 0; count = 0;cnt=0; scanf( "%d",&n ); for( int i = 0 ; i < n ; i ++ ) { scanf( "%d",&num ); p[cnt++] = rec[num]; tx[count++] = rec[num].x1; tx[count++] = rec[num].x2; } sort( p , p + cnt , cmp1 ); sort( tx , tx + count , cmp2 ); for( int i = 1 ; i < count ; i ++ ) if( tx[i-1]!=tx[i] ) { left[t] = tx[i-1]; right[t++] = tx[i]; // printf( "%d %d %d\n",left[t-1],right[t-1],t ); } int ans = 0; for( int i = 0 ; i < t ; i ++ ) { int up = -1 , down = -1; for( int j = 0 ; j < cnt ; j ++ ) { if( left[i]>=p[j].x1 && right[i]<=p[j].x2 ) { if( up < p[j].y1 ) { ans += ( right[i] - left[i] )*( up - down ); up = p[j].y2; down = p[j].y1; } else if( up < p[j].y2 ) up = p[j].y2; } } ans += ( right[i] - left[i] )*( up - down ); // printf( "ans=%d %d %d %d\n",ans,up,down,right[i]- left[i] ); } printf( "Query %d: %d\n",k,ans ); } } int main( ) { int Case = 1; while( scanf( "%d%d",&N,&M ),N|M ) { for( int i = 1 ; i <= N ; i ++ ) { scanf( "%d%d%d%d",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2 ); } printf( "Case %d:\n",Case++ ); Solve( ); puts( "" ); } //system( "pause" ); return 0; }