Codeforces Round #295 (Div. 2) D.Cubes(STL)

题目:

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

题意:

有n 个点坐标(xi,yi)在坐标平面内,分别编号0~m.

在图上取点,每一次都要使图平衡.平衡的条件是:点(x,y) 在x 轴上,或者是(x,y-1) / (x-1,y-1) / (x+1, y-1) 上有点存在.

现在有两人a和b玩游戏, a先取数,每次取数都要保持图平衡.取到的数组成n进制的数.a要使得数越大,b使得数越小.

思路:

看了别人的代码了解的思路.

使用map存储所有的点坐标和编号.

先枚举所有的点,判断是否可以取,若可以则加入set -leap.

接着开始取数, i 为偶时,从leaf 尾取数, 奇时从头取数. 每次取完, 都要删除leaf中的标号, 且更新与它相关联的点, 看是否可以存在set中被取数.

AC.

#include <iostream>
#include <cstdio>
#include <map>
#include <set>


using namespace std;
typedef long long ll;
const ll mod = 1e9 + 9;
const int MAX = 100005;
map<pair<int, int>, int> ma;
set<pair<int, int> > s;
set<int> leaf;
int x[MAX], y[MAX], n;

void read()
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++i) {
        scanf("%d %d", &x[i], &y[i]);
        pair<int, int> p = make_pair(x[i], y[i]);
        ma[p] = i;
        s.insert(p);
    }
}
int cnt(int xx, int yy)
{
    int res = 0;
    for(int i = xx - 1; i <= xx + 1; ++i) {
        if(s.find(make_pair(i, yy - 1)) != s.end()) res++;
    }
    return res;
}
bool isleaf(int xx, int yy)
{
    for(int i = xx - 1; i <= xx + 1; ++i) {
        if(s.find(make_pair(i, yy+1)) != s.end() &&
            cnt(i, yy+1) == 1) return false;
    }
    return true;
}
void update(int xx, int yy)
{
    for(int i = xx - 2; i <= xx + 2; ++i) {
        for(int j = yy - 1; j <= yy + 1; ++j) {
            pair<int, int> p = make_pair(i, j);
            if(s.find(p) == s.end()) continue;
            int id = ma[p];
            if(leaf.find(id) != leaf.end()) leaf.erase(id);
            if(isleaf(i, j)) leaf.insert(id);
        }
    }
}
void work()
{
    for(int i = 0; i < n; ++i) {
        if(isleaf(x[i], y[i])) leaf.insert(i);
    }

    ll ans = 0;
    for(int i = 0; i < n; ++i) {
        int num;
        if(i % 2 == 0) num = *(--leaf.end());
        else num = *(leaf.begin());
        ans = (ans*n + num) % mod;
        s.erase(make_pair(x[num], y[num]));
        leaf.erase(num);
        update(x[num], y[num]);
    }

    printf("%I64d\n", ans);
}
int main()
{
//freopen("in", "r", stdin);

    read();
    work();

    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值