【CF 520D】Cubes

【CF 520D】Cubes

怎么说呢……英语阅读题+超级大模拟……
最重要的是知道怎么出来的数据。。。题意好懂
xy坐标内给出几个单位正方形 以正方形左下点坐标给出
y=0为地面 正方形下面或者左右下方至少存在一个正方形他才能稳定。。
正方形按0~m-1标号 每次只能取出不影响整体结构的正方形
甲乙玩一个游戏 交替取正方形 每取下一个按从左到右的顺序排好 得到一个大数 重点来了!
取出的数是m进制 转换为十进制是最终结果 甲希望结果最大 乙希望结果最小 问结果为多少 甲先取
题意明白了模拟就行 开两个优先队列分别给甲(递减)乙(递增) 再开个Map用来查询正方形编号
先把所有能取的正方形编号存进去 每取出一个看他左下 下 右下有没有正方形并判断去除这些正方形影不影响剩余结构 不影响就存入队列 同时判断左上 上 右上存不存在正方形 并看取走这个正方形后他们下面其他的正方形还可不可取 不可取的话标记下 下次队列遍历到不要取走 最后把m进制转换二进制输出即可

代码如下:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <list>
#include <map>
#define mod 1000000009
#define ll long long
//#define Debug

using namespace std;

pair <int,int> sq[100005];
priority_queue <int,vector<int>,greater<int> > small;
priority_queue <int,vector<int>,less<int> > big;
map <pair<int,int>,int> gt;
int has[100005];//-1 图内/不能选择 1队列内 0已组合
ll pex[100005],sum;

void Init(int m)
{
    pex[1] = 1;
    for(int i = 2; i <= m; ++i) pex[i] = (pex[i-1]*m)%mod;
    memset(has,-1,sizeof(has));
}

bool hs(int x,int y)
{
    return (gt.count(pair<int,int> (x,y)) && has[gt[pair<int,int> (x,y)]] != 0);
}

bool Stable(int x,int y)
{
    if(!hs(x,y)) return true;
    int t = 0;
    if(hs(x-1,y-1)) t++;
    if(hs(x,y-1)) t++;
    if(hs(x+1,y-1)) t++;
    if(t >= 2) return true;
    return false;
}

void Add(int x,int y,int i)
{
    if(has[i] == -1 && Stable(x+1,y+1) && Stable(x,y+1) && Stable(x-1,y+1))
    {
        #ifdef Debug
        printf("*%d\n",i);
        #endif // Debug
        big.push(i);
        small.push(i);
        has[i] = 1;
    }
}

void Clr(int t,int s)
{
    #ifdef Debug
    printf("%d\n",t);
    #endif
    sum = (sum + (t*pex[s])%mod)%mod;
    int x = sq[t].first;
    int y = sq[t].second;
    has[t] = 0;
    gt.erase(pair<int,int> (x,y));
    for(int i = 1; i >= -1; --i)
        if(hs(x+i,y+1) && !Stable(x+i,y+1))
        {
            if(i)
            {
                if(hs(x+i*2,y)) has[gt[pair<int,int> (x+i*2,y)]] = -1;
                if(hs(x+i,y)) has[gt[pair<int,int> (x+i,y)]] = -1;
            }
            else
            {
                if(hs(x+1,y)) has[gt[pair<int,int> (x+1,y)]] = -1;
                if(hs(x-1,y)) has[gt[pair<int,int> (x-1,y)]] = -1;
            }
        }

    for(int i = 1; i >= -1; --i)
        if(hs(x+i,y-1)) Add(x+i,y-1,gt[pair<int,int> (x+i,y-1)]);

}

int Vasa()
{
    int t = big.top();
    big.pop();
    while(has[t] != 1)
    {
        t = big.top();
        big.pop();
    }
    #ifdef Debug
    printf("bs%d\n",big.size());
    #endif
    return t;
}

int Peta()
{
    int t = small.top();
    small.pop();
    while(has[t] != 1)
    {
        t = small.top();
        small.pop();
    }
    #ifdef Debug
    printf("ss%d\n",small.size());
    #endif
    return t;
}

int main()
{
    int m,i,x,y,t;
    scanf("%d",&m);
    Init(m);

    for(i = 0; i < m; ++i)
    {
        scanf("%d %d",&x,&y);
        sq[i] = pair<int,int> (x,y);
        gt.insert(pair<pair<int,int>,int> (pair<int,int>(x,y),i));
    }

    for(i = 0; i < m; ++i)
    {
        x = sq[i].first;
        y = sq[i].second;
        Add(x,y,i);
    }
    sum = 0;
    for(i = 0; i < m; ++i)
    {
        if(i&1) t = Peta();
        else t = Vasa();
        Clr(t,m-i);
    }

    printf("%lld\n",sum);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Marching Cubes算法是一种常用的三维体数据表面重建算法。它可以将一个体数据集转化为连续的多边形网格模型。 在三维体数据中,每个体素的值表示其在某一属性上的特征,如密度、压力等。Marching Cubes算法首先将整个体数据集划分为无数个小立方体,每个小立方体包含8个顶点。然后根据每个小立方体顶点所代表的属性值与事先设定的阈值进行比较,确定该顶点是否在表面上。若在表面上,就将相应顶点连接起来组成一个面,并将该面连接到整个网格模型上。 得到的多边形网格模型可以用于可视化、仿真和分析等应用。Marching Cubes算法具有简单、高效的特点,适用于各种不规则的三维体数据集。它广泛应用于医学图像处理、地质勘探、计算机动画等领域。 然而,Marching Cubes算法也存在一些限制。首先,它在重建过程中产生的多边形可能存在不连续性和拓扑错误。为了解决这个问题,后续研究提出了一些改进算法,如Dual Marching Cubes和Extended Marching Cubes。其次,Marching Cubes算法对数据集的分辨率要求较高,对于过于细致的结构可能无法很好地重建。 总的来说,Marching Cubes算法在三维体数据表面重建领域具有重要的应用价值,其简单、高效的特点使其成为一种常用的算法。随着相关技术的不断发展,对Marching Cubes算法的改进和优化将进一步推动其在各个领域的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值