DoIt is Being Flooded
2015-11-16 19:46
369 查看
Description
Global warming affects the whole world right now. DoIt is a country which is surrounded by the sea and suffering from global warming. Scientists in DoIt find out that the sea level will rise 1 meter every year so that some places in DoIt will be flooded
and disappear from the earth. As a result, the country may be divided into several islands and finally disappear.
DoIt's government wants to know how much it can earn before the whole country's disappearance. Thanks for economists, its income can be decided by the size of unflooded places and an economic coefficientA.
A will change with years and it has been well forecasted by economists. The total income of DoIt is the sum of all islands' income. For each island, its income equals2 Bits(S & A).
S is the size of the island and A is the economic coefficient of that year.Bits(x) means the number of 1 in
x's binary code.
Assuming DoIt can be represented by n * m grids, an integer in a grid indicates its altitude. The size of a grid is 1. Two grids are adjacent if they have a common edge. Note that, water in a grid can only flow into grids which are adjacent
to the current grid. At first, it's year 0 and the sea level is 0. Therefore, in thed-th year, the sea level will rise to
d at the very begining of the year. There are several queries asked by the government. Each query includes two integers,d,
A, representing the year and the economic coefficient of that year. You should output DoIt's total income in thed-th year. You can assume that the sea level changes at the beginning of the year and keeps unchanged in that year. So the total
income is caclulated after this change.
Input
There are multiple test cases (about 10).
For each case, in the first line there are two integers n and m (1 ≤n,
m ≤ 500). Then in the next n lines, each line has m integers. It's guaranteed that all altitudes are larger than 0 and no more than 1000000.
After that, there is an integer Q (1 ≤ Q ≤ 10000), representing the number of queries. In the nextQ lines, each line has two integers,
d (1 ≤ d ≤ 1000000) andA (0 ≤ A ≤ 1000000000). It's possible that different economic coefficients are found in the same year.
Output
For each query, output the total income of DoIt in that year.
Sample Input
Sample Output
题意:
一个图,每个点为一个建筑物,在发生洪水的时候有多少建筑是没有被淹的,
注意一点就是洪水只能从相邻的位置流进去,样例当高度为3时,是淹不到
建筑物的,最后的结果就是2^(每个连通块的个数&A的二进制位的个数),
统计和就是答案。
这道题涉及的东西挺多的,需要用优先队列将相邻的值设置成较大(开始只保存边界就行),
只能从边界流进去,所以每次出最小的值能流到的位置然后设置较大的那个值,然后
保存所有的值,这样就可以通过从大到小统计连通块,并统计每个连通块的个数,先
将答案预处理,然后只需要输出就行,保存答案时用数组就行,开始用map内存超限。
Global warming affects the whole world right now. DoIt is a country which is surrounded by the sea and suffering from global warming. Scientists in DoIt find out that the sea level will rise 1 meter every year so that some places in DoIt will be flooded
and disappear from the earth. As a result, the country may be divided into several islands and finally disappear.
DoIt's government wants to know how much it can earn before the whole country's disappearance. Thanks for economists, its income can be decided by the size of unflooded places and an economic coefficientA.
A will change with years and it has been well forecasted by economists. The total income of DoIt is the sum of all islands' income. For each island, its income equals2 Bits(S & A).
S is the size of the island and A is the economic coefficient of that year.Bits(x) means the number of 1 in
x's binary code.
Assuming DoIt can be represented by n * m grids, an integer in a grid indicates its altitude. The size of a grid is 1. Two grids are adjacent if they have a common edge. Note that, water in a grid can only flow into grids which are adjacent
to the current grid. At first, it's year 0 and the sea level is 0. Therefore, in thed-th year, the sea level will rise to
d at the very begining of the year. There are several queries asked by the government. Each query includes two integers,d,
A, representing the year and the economic coefficient of that year. You should output DoIt's total income in thed-th year. You can assume that the sea level changes at the beginning of the year and keeps unchanged in that year. So the total
income is caclulated after this change.
Input
There are multiple test cases (about 10).
For each case, in the first line there are two integers n and m (1 ≤n,
m ≤ 500). Then in the next n lines, each line has m integers. It's guaranteed that all altitudes are larger than 0 and no more than 1000000.
After that, there is an integer Q (1 ≤ Q ≤ 10000), representing the number of queries. In the nextQ lines, each line has two integers,
d (1 ≤ d ≤ 1000000) andA (0 ≤ A ≤ 1000000000). It's possible that different economic coefficients are found in the same year.
Output
For each query, output the total income of DoIt in that year.
Sample Input
5 5 6 6 6 6 8 5 2 2 2 5 5 2 3 2 4 8 2 1 1 5 7 4 5 5 5 4 3 255 5 255 7 255 9 255
Sample Output
8 6 4 0
Hint
Because of the large input, scanf is recommended.题意:
一个图,每个点为一个建筑物,在发生洪水的时候有多少建筑是没有被淹的,
注意一点就是洪水只能从相邻的位置流进去,样例当高度为3时,是淹不到
建筑物的,最后的结果就是2^(每个连通块的个数&A的二进制位的个数),
统计和就是答案。
这道题涉及的东西挺多的,需要用优先队列将相邻的值设置成较大(开始只保存边界就行),
只能从边界流进去,所以每次出最小的值能流到的位置然后设置较大的那个值,然后
保存所有的值,这样就可以通过从大到小统计连通块,并统计每个连通块的个数,先
将答案预处理,然后只需要输出就行,保存答案时用数组就行,开始用map内存超限。
#include <stdio.h> #include <queue> #include <map> #include <algorithm> #include <string.h> using namespace std; #define CLR( a ) memset ( a, 0, sizeof ( a ) ) #define LL long long #define DBUG printf ( "Here!\n" ) const int maxn = 505, M = maxn*maxn, QY = 10005; const int dx[4] = { 0, 1, -1, 0 }, dy[4] = { 1, 0, 0, -1 }; int mp[maxn][maxn], n, m; int father[M], num[M], ans[QY]; map < int, int > cur; bool vis[maxn][maxn]; struct node { int h, x, y; friend bool operator < ( node n1, node n2 ) {//优先队列小的先出,排序就是降序 return n1.h > n2.h; } } nd[M], t; struct query { int d, a, i; friend bool operator < ( query q1, query q2 ) { return q1.d > q2.d; } }qry[QY]; priority_queue < node > q; inline int Max ( int a, int b ) { return a > b ? a : b; } inline bool check ( int x, int y ) { return x < 0 || x >= n || y < 0 || y >= m; } void init ( ) { for ( int i = 0; i <= n*m; i ++ ) { father[i] = i; num[i] = 1; } CLR ( vis ); cur.clear ( ); } int find ( int x ) { int r = x, i, j; while ( r != father[r] ) r = father[r]; i = x; while ( i != r ) { j = father[i]; father[i] = r; i = j; } return r; } void merge ( int fx, int fy ) { father[fy] = fx; num[fx] = num[fx]+num[fy]; } int bit_cnt ( int n ) { int ret = 0; while ( n > 0 ) { if ( n&1 ) ret ++; n = n >> 1; } return ret; } int main ( ) { int cnt, Q; while ( ~ scanf ( "%d%d", &n, &m ) ) { cnt = 0; CLR ( vis ); while ( ! q.empty ( ) ) //清空 q.pop ( ); for ( int i = 0; i < n; i ++ ) for ( int j = 0; j < m; j ++ ) { scanf ( "%d", &mp[i][j] ); if ( i == 0 || j == 0 || i == n-1 || j == m-1 ) { nd[cnt].x = i, nd[cnt].y = j, nd[cnt].h = mp[i][j]; q.push ( nd[cnt] ); //将边界保存 cnt ++; vis[i][j] = true; } } while ( ! q.empty ( ) ) { t = q.top ( ); q.pop ( ); for ( int i = 0; i < 4; i ++ ) { //将最小值相邻设置成两个中比较大的那个 int nx = t.x+dx[i]; int ny = t.y+dy[i]; if ( check ( nx, ny ) || vis[nx][ny] ) continue ; vis[nx][ny] = true; //标记 mp[nx][ny] = Max ( mp[nx][ny], mp[t.x][t.y] ); //设置成两个中间较大的值 nd[cnt].x = nx, nd[cnt].y = ny, nd[cnt].h = mp[nx][ny]; q.push ( nd[cnt] ); cnt ++; } } sort ( nd, nd+cnt ); //降序 scanf ( "%d", &Q ); for ( int i = 0; i < Q; i ++ ) { scanf ( "%d%d", &qry[i].d, &qry[i].a ); qry[i].i = i; //注意将编号保存,输出的时候就可以直接输出 } sort ( qry, qry+Q ); //对高度降序,那样就可以直接统计连通块块数和每块的个数 init ( ); for ( int i = 0, c = 0; i < Q; i ++ ) { while ( c < cnt && nd[c].h > qry[i].d ) //统计所有高度大于d的个数,和连通块数 { int x = nd[c].x, y = nd[c].y; vis[x][y] = true; //标记有此数 cur[1] ++; //1个的个数加1 for ( int j = 0; j < 4; j ++ ) //判断连通的个数 { int nx = x+dx[j]; int ny = y+dy[j]; if ( check ( nx, ny ) || vis[nx][ny] == false ) continue ; int a = x*m+y, b = nx*m+ny; //将二维换成一维的坐标 int fa = find ( a ), fb = find ( b ); if ( fa != fb ) { cur[ num[fa] ] --; //fa连通块的个数减1 if ( cur[ num[fa] ] == 0 ) //为0时删除 cur.erase ( num[fa] ); cur[ num[fb] ] --; //fb同理 if ( cur[ num[fb] ] == 0 ) cur.erase ( num[fb] ); merge ( fa, fb ); //合并 将总个数求出 cur[ num[fa] ] ++; //统计连通个数为num[fa]的个数 } } c ++; } int val = 0; for ( map < int, int > :: iterator it = cur.begin ( ); it != cur.end ( ); it ++ ) val = val+( ( *it ).second << bit_cnt ( ( *it ).first & qry[i].a ) ); //迭代map,个数*( 1 << bit_cnt ( cnt & A ) ) ans[ qry[i].i ] = val; //下标qry[i].i的值为val } for ( int i = 0; i < Q; i ++ ) printf ( "%d\n", ans[i] ); } return 0; }
相关文章推荐
- Object-c 中Extension解析
- javaSE(01)
- windows IIS安装memadmin
- 本地代码导入github仓库
- CDA数据分析师培训笔记(一)20151114-20151115
- spark shuffle内存申请策略
- android 之 自定义圆形头像
- 文章标题 接口回调的思想
- Spring自定义缓存管理及配置Ehcache缓存
- 算法系统学习-经典基础算法-全排列算法
- 产品经理几个关键点
- 转:c/c++内存释放知识总结
- 利用按钮来执行命令
- Java多线程同步
- setTimeOutInMilliSeconds
- LeetCode H-Index 数组
- android应用层相关设置及命令(二)
- 单片机应用编程技巧问答
- 从Script到Code Blocks、Code Behind到MVC、MVP、MVVM
- 《C++并发编程实战》读书笔记6---设计并发代码