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

你可能感兴趣的:(并查集,字典树,欧拉图,大模拟)