Abstract

Codeforces 105D

并查集(官方标的)

Body

Source

http://codeforces.com/problemset/problem/105/D

Description

题意很复杂,自己看……我一开始也没看懂,把那个gif动态图看个10遍以上就懂了。

http://212.193.37.254/codeforces/images/geo_slow.gif

Solution

比较裸的并查集。注意到染色操作实际上就是将原本颜色不同的格子合并到一起即可。计算螺旋形距离的话,实际上只跟格子相对中心格的坐标有关。我是直接找公式,CF上面的代码好像大部分是直接记录,各种step++什么的,看不懂。

但是仔细分析后我觉得,其实和并查集没有什么关系……令当前需要染色的格子集合为S。可以证明,实际上每次染色只会把别的格子并入S,而不会从S中删除或换掉格子(尽管S的颜色不断改变)。于是只用记录S的颜色和大小即可。

P.S. 写得这么简陋还叫解题报告实在是太不好意思了,以后标签改成[代码]好了。

Code

并查集(我写的并查集很长很难看,大家还是看CF上面的代码好了)

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <vector>#include <queue>#include <map>using namespace std;

const int S = 303*303*2;

typedef long long LL;typedef pair<int, int> pr;pr (*mkpr)(int, int)=make_pair;

int N, M;LL ans = 0;map<int, int> color;int f[S], r[S], c[S], s[S];int pan[303][303], sym[303][303];int colorcnt = 0;vector<pr> node[S];queue<pr> q;pr now;int cnow, cchg;

inline int getcolor(int x){if (!color.count(x)) color[x] = colorcnt++;return color[x];}

inline int dis(int i, int j){int n;if (j <= 0) n = max(abs(j), abs(i)-1);else n = max(abs(j), abs(i))-1;if (i==n+1) return 4*(n+1)*(n+1)+(n+1)-j;else if (j==n+1) return (4*n+2)*(n+1)+(n+1)+i;else if (i==-n-1) return (2*n+1)*(2*n+1)+n+j;else return 4*n*n+2*n+n-i;}

bool cmp(const pr &u, const pr &v){return dis(u.first-now.first, u.second-now.second)<dis(v.first-now.first, v.second-now.second);}

int find(int x){if (f[x]==x) return x;return f[x] = find(f[x]);}

int join(int u, int v){int ru = find(u), rv = find(v);if (ru == rv) return ru;if (r[ru]<r[rv])    {        s[rv] += s[ru];        s[ru] = 0;return f[ru] = rv;    }else if (r[rv]<r[ru])    {        s[ru] += s[rv];        s[rv] = 0;return f[rv] = ru;    }else    {        r[rv]++;        s[rv] += s[ru];        s[ru] = 0;return f[ru] = rv;    }}

void init(){for (int i = 0; i < colorcnt; ++i)    {        f[i] = i;        c[i] = i;        r[i] = 0;    }}

int main(){int i, j, k, x, y, root;    scanf("%d%d", &N, &M);    color[0] = colorcnt++;for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)        {            scanf("%d", &pan[i][j]);            pan[i][j] = getcolor(pan[i][j]);            s[pan[i][j]]++;        }for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)        {            scanf("%d", &sym[i][j]);if (sym[i][j]!=-1) sym[i][j] = getcolor(sym[i][j]);        }    init();    scanf("%d%d", &x, &y);    x--; y--;for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)if (i==x&&j==y) q.push(mkpr(i, j));else if (sym[i][j]!=-1) node[pan[i][j]].push_back(mkpr(i, j));while (!q.empty())    {        now = q.front(); q.pop();        i = now.first, j = now.second;        root = find(pan[i][j]);        cnow = c[root]; cchg = sym[i][j];if (cnow==0 || cnow==cchg) continue;        ans += s[root];        vector<pr> elm = node[cnow];        node[cnow].clear();        sort(elm.begin(), elm.end(), cmp);for (k = 0; k < elm.size(); ++k)            q.push(elm[k]);        f[cchg] = cchg;        c[join(root, cchg)] = cchg;    }    cout << ans << endl;}

非并查集

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <vector>#include <queue>#include <map>using namespace std;

const int S = 303*303*2;

typedef long long LL;typedef pair<int, int> pr;pr (*mkpr)(int, int)=make_pair;

int N, M;LL ans = 0;map<int, int> color;int s[S];int pan[303][303], sym[303][303];int colorcnt = 0;vector<pr> node[S];queue<pr> q;pr now;int snow, cnow, cchg;

inline int getcolor(int x){if (!color.count(x)) color[x] = colorcnt++;return color[x];}

inline int dis(int i, int j){int n;if (j <= 0) n = max(abs(j), abs(i)-1);else n = max(abs(j), abs(i))-1;if (i==n+1) return 4*(n+1)*(n+1)+(n+1)-j;else if (j==n+1) return (4*n+2)*(n+1)+(n+1)+i;else if (i==-n-1) return (2*n+1)*(2*n+1)+n+j;else return 4*n*n+2*n+n-i;}

bool cmp(const pr &u, const pr &v){return dis(u.first-now.first, u.second-now.second)<dis(v.first-now.first, v.second-now.second);}

int main(){int i, j, k, x, y;    scanf("%d%d", &N, &M);    color[0] = colorcnt++;for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)        {            scanf("%d", &pan[i][j]);            pan[i][j] = getcolor(pan[i][j]);            s[pan[i][j]]++;        }for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)        {            scanf("%d", &sym[i][j]);if (sym[i][j]!=-1) sym[i][j] = getcolor(sym[i][j]);        }    scanf("%d%d", &x, &y);    x--; y--;for (i = 0; i < N; ++i)for (j = 0; j < M; ++j)if (i==x&&j==y) q.push(mkpr(i, j));else if (sym[i][j]!=-1) node[pan[i][j]].push_back(mkpr(i, j));    cnow = pan[x][y]; snow = 0;while (!q.empty())    {        now = q.front(); q.pop();        i = now.first, j = now.second;        cchg = sym[i][j];if (cnow==0 || cnow==cchg) continue;        snow += s[cnow];        s[cnow] = 0;        ans += snow;        vector<pr> elm = node[cnow];        node[cnow].clear();        sort(elm.begin(), elm.end(), cmp);for (k = 0; k < elm.size(); ++k)            q.push(elm[k]);        cnow = cchg;    }    cout << ans << endl;}

转载于:https://www.cnblogs.com/jffifa/archive/2012/03/21/2410295.html

[解题报告]Codeforces 105D Entertaining Geodetics相关推荐

  1. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  2. Codeforces Round #700 (Div. 2)A~D2解题报告

    Codeforces Round #700 (Div. 2)A~D2解题报告 A Yet Another String Game 原题链接 http://codeforces.com/contest/ ...

  3. Codeforces Round #693 (Div. 3)A~G解题报告

    Codeforces Round #693 (Div. 3)A~G解题报告 A Cards for Friends 原题信息 http://codeforces.com/contest/1472/pr ...

  4. Codeforces Round #697 (Div. 3)A~G解题报告

    Codeforces Round #697 (Div. 3)A~G解题报告 题 A Odd Divisor 题目介绍 解题思路 乍一想本题,感觉有点迷迷糊糊,但是证难则反,直接考虑没有奇数因子的情况, ...

  5. Codeforces Round #698 (Div. 2) A-E解题报告与解法证明

    Codeforces Round #698 (Div. 2) A-E解题报告与解法证明 题目解法总体概括 A Nezzar and Colorful Balls #include <bits/s ...

  6. Codeforces round 654 赛后解题报告

    Codeforces round 654 赛后解题报告 先吐槽一下怎么 A-D 都是结论题啊啊 A. Magical Sticks 我们可以先确定下来,我们一定只对于未进行过拼接的木棍拼接. 学过等差 ...

  7. Codeforces Round #677 (Div. 3)——ABCDE解题报告

    Codeforces Round #677 (Div. 3)--ABCDE解题报告 比赛链接:https://codeforces.com/contest/1433 A.Boring Apartmen ...

  8. codeforces 50A-C语言解题报告

    50A题目网址 解题报告-others 题目解析 1.输入n x m大小的木板,使用21大小的多米诺去填满,求最多的多米诺数目 2.通过分析把木板分为奇数和偶数的情况 1)有一边是偶数的情况: 使用2 ...

  9. Codeforces 438D 线段树 解题报告

    D. The Child and Sequence At the children's day, the child came to Picks's house, and messed his hou ...

最新文章

  1. 有了实例化需求,交付高质量软件不再是空谈
  2. 网站建设案例欣赏_网站制作设计案例_成都辰星建站
  3. 文件映射操作类的实现
  4. 机器人学习--Turtelbot3学习--如何使用cartographer建图
  5. java web如何配置ask_Javaweb新手之路之JavaWeb开发环境配置篇
  6. mysql工具的使用_产品操作MySQL入门篇-工具使用
  7. 选项卡,下拉菜单操做时的页面数据更新,highcharts,d3 结合。
  8. python开发中遇到的难题_初学者在Python开发中常见的问题(上)
  9. 拜登将主持商讨网络安全问题,苹果和微软CEO参加
  10. php脚本搭vps,#分享#基于宝塔面板的ZFaka(发卡程序)一键脚本
  11. GNOME下也是Alt+F2,输入gnome-terminal
  12. java 标题栏_如何更改java应用程序标题栏默认图标
  13. 格拉布斯法—异常值判断(异常值)
  14. php eclipse 版本_PHPEclipse官方下载
  15. 8家供应商、2300个特效镜头,ftrack助力《侍神令》协同制作
  16. 37个自学网站,一年让你省下十几万
  17. 《研究生科研能力训练与培养》
  18. 360全景拍摄中相机的白平衡设置
  19. 微服务之间调用的安全认证-jwt
  20. 国内主要的PDM产品关于浏览圈阅模块的总结(2006)

热门文章

  1. 理解 Redux 的最好方式,是自己写一个
  2. React 高级应用 -- 错误边界 Error Boundaries
  3. 乱码385b1b926a38153d38957556c0dc55b5
  4. cygwin 解决 乱码问题 (转)
  5. Linux下bash:command not found提示
  6. JS---Math.Random()*10--[0,10)随机变颜色
  7. hibernate4.3 无法获取数据库最新值
  8. openstack network
  9. unity, destroy gameObject destroy all children
  10. linux笔记:linux帮助命令,man,help,whatis,apropos