1 条题解
-
0
首先,这题的输入就很恶心,我们可以用下面的代码成功输入:
for(int i = 1;i <= n; i++) { cin >> str; if(str == ";")continue; int l = 0, r = 0, num = 0; int type = 0; for(int j = 0;j < str.size(); j++) { if(isdigit(str[j]) && type == 0) { num = num * 10 + (str[j] - '0'); } else if(type == 2 && isdigit(str[j])) { r = r * 10 + (str[j] - '0'); } else if(str[j] == '-') { type = 2; l = num; } else if(str[j] == ',' || str[j] == ';') { if(type == 2)update(i, l, r);//将l~r涂成黑色 else update(i, num, num);//将num涂成黑色 num = l = r = 0; type = 0; } }
其中,
update(i, l, r)
表示第 行的 的这些方块涂成黑色,具体什么内容就看我们要用哪种方法做这道题。暴力
直接暴力跑一个 ,能拿到大概 分并且附上 的好成绩(bushi)
/***************************************** 备注:solution1 ******************************************/ #include<queue> #include<math.h> #include<stack> #include<stdio.h> #include<iostream> #include<vector> #include<iomanip> #include<map> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; const int MAXN = 1e4 + 10; const int MR = 1e6 + 10; const int INF = 0x3f3f3f3f; const int MOD = 998244353; const int debug = false; const int debug1 = false; int mp[MAXN][MAXN] = {0}; int idx[MAXN][MAXN] = {0};//color int n; void update(int h, int l, int r)//color the l~r { for(int kkk = l;kkk <= r; kkk++)mp[h][kkk] = 1;//start color } void print()//print the map { for(int i = 1;i <= n; i++) { for(int j = 1;j <= n; j++) { cout << mp[i][j] << ' '; } cout << endl; } } void dfs(int row,int col,int id) { if (row < 1 || row > n || col < 1 || col > n)return; if((mp[row][col] != 1) || (idx[row][col] > 0)) return; idx[row][col] = id; for(int drow=-1;drow<=1;drow++){ for(int dcol=-1;dcol<=1;dcol++){ dfs(row + drow, col + dcol, id); } } } int len[MR]; struct node { int num, appear;//什么数字 长度 }box[MR]; bool cmp(node a,node b) { return a.num > b.num; } signed main() { cin >> n; string str; for(int i = 1;i <= n; i++) { cin >> str; if(str == ";")continue; int l = 0, r = 0, num = 0; int type = 0; for(int j = 0;j < str.size(); j++) { if(isdigit(str[j]) && type == 0) { num = num * 10 + (str[j] - '0'); } else if(type == 2 && isdigit(str[j])) { r = r * 10 + (str[j] - '0'); } else if(str[j] == '-') { type = 2; l = num; } else if(str[j] == ',' || str[j] == ';') { if(debug)printf("num:%d l:%d r:%d type:%d\n", num, l, r, type); if(type == 2)update(i, l, r);//update block l~r else update(i, num, num);//update block num num = l = r = 0; type = 0; } } } int cnt = 0; for(int i = 1;i <= n; i++) { for(int j = 1;j <= n; j++) { if(idx[i][j] == 0 && mp[i][j] == 1) { dfs(i, j, ++cnt); } } } if(debug1)cout << cnt << endl; for(int i = 1;i <= n; i++) { for(int j = 1;j <= n; j++) { len[idx[i][j]]++; } } int mxx = -INF; for(int i = 1;i <= cnt; i++)box[len[i]].appear++, box[len[i]].num = len[i], mxx = max(mxx, len[i]); sort(box + 1,box + mxx + 1, cmp); for(int i = 1;i <= cnt; i++) { if(box[i].num == 0 || box[i].appear == 0)continue; cout << box[i].num << ' ' << box[i].appear << endl; } if(debug1){cout << endl; print();} return 0; }
这代码甚至没有 ,太感动了。
因为是 ,棋盘放不下
所以分析个 啊(,接下来我们考虑优化。优化
首先,我们把这个图画出来
连通块就是指 连通的块,我们可以这样子想,只看两行,题目说过不超过 ,我们可以就 储存黑格子 有多少个。什么意思呢,就是当前如果和上一行的黑格子相邻,我们就将这两个格子 合并 一个格子,然后再判断左右两边的格子和这个合并的格子相不相邻,然后把他们 看成一块,这样的方法我们可以用什么数据结构存储呢?当然是 并查集 了,当然维护并查集我们还需要一个数组 来储存大小,那么这题思路就讲完了,直接看代码吧。
/***************************************** 备注: ******************************************/ #include<queue> #include<math.h> #include<stack> #include<stdio.h> #include<iostream> #include<vector> #include<iomanip> #include<map> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define int LL const int MAXN = 1e6 + 10; const int MR = 10 + 5; const int INF = 0x3f3f3f3f; const int MOD = 998244353; int fa[MAXN],siz[MAXN], cnt; int now[MAXN], pre[MAXN]; int get(int x) { return fa[x] == x ? x : fa[x] = get(fa[x]); } void merge(int x,int y) { x = get(x);y = get(y); if(x == y)return ; if(siz[x] < siz[y]) { fa[x] = y; siz[y] += siz[x]; } else { fa[y] = x; siz[x] += siz[y]; } } int make_new(){siz[++cnt] = 1;return cnt;} signed main() { for(int i = 1;i <= 1000000; i++)fa[i] = i; int n;string str; cin >> n; for(int i = 1;i <= n; i++) { memcpy(pre, now, sizeof(pre)); memset(now, 0, sizeof(now)); cin >> str; if(str == ";")continue; int l = 0, r = 0, num = 0; int type = 0; for(int j = 0;j < str.size(); j++) { if(isdigit(str[j]) && type == 0) { num = num * 10 + (str[j] - '0'); } else if(type == 2 && isdigit(str[j])) { r = r * 10 + (str[j] - '0'); } else if(str[j] == '-') { type = 2; l = num; } else if(str[j] == ',' || str[j] == ';') { if(type == 0) { //only one now[num] = make_new(); if(pre[num])merge(now[num], pre[num]);//如果上一行是黑色的 } else if(type == 2) { now[l] = make_new(); if(pre[l])merge(now[l], pre[l]);//如果上一行是黑色的 for(int huhe = l + 1;huhe <= r; huhe++) { now[huhe] = make_new(); if(pre[huhe])merge(pre[huhe], now[huhe]); merge(now[huhe], now[huhe - 1]); } } num = l = r = 0; type = 0; } } } int ans[MAXN]; for(int i = 1;i <= cnt; i++)if(fa[i] == i)ans[siz[i]] ++; for(int i = 1000;i >= 1; i--) { if(ans[i] >= 1)cout << i << ' ' << ans[i] << endl; } return 0; }
这代码甚至 ,太感动了(
为什么呢,因为 可能每次的 的暴力操作再配上并查集合并操作就会炸掉。考虑再优化一下。
直接将每次输入的 得格式的格子创建一个大的连通块, 当前的 ,然后判断当前这个连通块和上一行有没有相交即可。
(注意:并查集初始化一定要变成 ,我在这里卡了 )
AC 代码
/***************************************** 备注: ******************************************/ #include<queue> #include<math.h> #include<stack> #include<stdio.h> #include<iostream> #include<vector> #include<iomanip> #include<map> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define int LL const int MAXN = 1e6 + 10; const int MR = 10 + 5; const int INF = 0x3f3f3f3f; const int MOD = 998244353; int fa[MAXN],siz[MAXN], cnt; char str[MAXN]; struct node { int l, r, pos;//l ~ r的黑格子,pos表示上一行第pos位跟当前的l~r有相邻 }now[MAXN], pre[MAXN]; int ncnt, pcnt; int ans[MAXN]; int get(int x) { return fa[x] == x ? x : fa[x] = get(fa[x]); } void merge(int x,int y) { x = get(x);y = get(y); if(x == y)return ; if(siz[x] < siz[y]) { fa[x] = y; siz[y] += siz[x]; } else { fa[y] = x; siz[x] += siz[y]; } } int make_new(int x){siz[++cnt] = x;return cnt;} void copy() { for(int i = 1;i <= ncnt; i++) { pre[i] = now[i]; now[i] = {0, 0, 0}; } pcnt = ncnt,ncnt = 0; } int read(int &j) { int r = 0; while(isdigit(str[j]))r = r * 10 + (str[j++] - '0'); return r; } signed main() { for(int i = 1;i <= 1000000; i++)fa[i] = i; int n; cin >> n; for(int i = 1;i <= n; i++) { // copy(); memcpy(pre,now,sizeof(node)*ncnt); pcnt = ncnt,ncnt = 0; int pos = 0; cin >> (str + 1); for(int j = 1;j <= strlen(str+1); j++) { if(str[j] == ';')break ; int l = read(j), r = l; if(str[j] == '-') { j++; r = read(j); } now[ncnt] = {l, r, make_new(r - l +1)}; for(;pos < pcnt && pre[pos].r < l; pos++) { } for(;pos < pcnt && pre[pos].l <= r; pos++) { merge(now[ncnt].pos, pre[pos].pos); } ncnt++; if(pos)pos--; } } for(int i = 1;i <= cnt; i++)if(fa[i] == i)ans[siz[i]] ++; for(int i = 1000;i > 0; i--) { if(ans[i])cout << i << ' ' << ans[i] << endl; } return 0; }
- 1
信息
- ID
- 1364
- 时间
- 5000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 16
- 已通过
- 1
- 上传者