zoukankan      html  css  js  c++  java
  • [解题报告]Codeforces 105D Entertaining Geodetics

    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;
    }




  • 相关阅读:
    Visual Studio调试器指南---Disassembly窗口
    Visual Studio调试器指南---Register窗口
    Visual Studio调试器指南---Threads窗口
    关于System.Convert.ToInt16(float value)抛异常System.OverflowException---值对于 Int32 太大或太小的原因的探究
    关于System.OverflowException异常
    Visual Studio调试器指南---Memory 1-4窗口
    关于异常System.NullReferenceException
    关于C++标准异常之std::out_of_range
    VC调试器高级应用----高级断点篇
    Visual Studio调试器指南---CallStack窗口
  • 原文地址:https://www.cnblogs.com/jffifa/p/2410295.html
Copyright © 2011-2022 走看看