hdc 4056 Draw a Mess(路径压缩)

题意:给出一个n*m的矩阵(n<=200,m<=50000)和9种颜色,以及如下4种操作:1.将矩阵中的一块圆形区域 (x - xc)2 + (y - yc)2 ≤ r2 全涂成颜色 c。2.将矩阵中的一块菱形区域 abs(x - xc) + abs(y - yc) ≤ r 全涂成颜色 c。3.将矩阵中的一块矩形区域 xc ≤ x ≤ xc+l-1, yc ≤ y ≤ yc+w-1 全涂成颜色 c。4.将矩阵中的一块三角形区域全涂成颜色c。问最后这每种颜色的格子数。

倒着处理所有的操作,将所有染色的格子删除,用并查集类似路径压缩的方法去快速寻找下一个没有染色的格子。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=201;
const int M=50005;
int n,m,q;
char str[55];
struct node
{
    int type,cnt,data[5];
    void input()
    {
        scanf("%s",str);
        if(strcmp(str,"Circle")==0) cnt=4,type=0;
        else if(strcmp(str,"Diamond")==0) cnt=4,type=1;
        else if(strcmp(str,"Rectangle")==0) cnt=5,type=2;
        else cnt=4,type=3;
        for(int i=0;i<cnt;i++) scanf("%d",&data[i]);
    }
}op[M];
struct List {
    bool vis[M];
    int rht[M];
    void clear()
    {
        for(int i=0;i<m;i++) vis[i]=0,rht[i]=i+1;
    }
    int jump(int pos)
    {
        if(!vis[pos]) return pos;
        else return rht[pos]=jump(rht[pos]);
    }
    int erase(int st, int ed)
    {
        st=max(0,st);   ed=min(m-1,ed);
        int sum=0,pos=jump(st);
        while (pos<=ed)
        {
            ++sum;
            vis[pos]=1;
            pos=jump(pos);
        }
        return sum;
    }
}row[N];
int main()
{
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        int cnt[12]={0};
        for(int i=0;i<n;i++) row[i].clear();
        for(int i=0;i<q;i++) op[i].input();
        for(int i=q-1;i>=0;i--)
        {
            if(op[i].type==0)
            {
                int xc=op[i].data[0];
                int yc=op[i].data[1];
                int r=op[i].data[2];
                int c=op[i].data[3];
                for(int x=max(0,xc-r);x<=min(n-1,xc+r);x++)
                {
                    int dis=floor(sqrt(1.0*r*r-1.0*(x-xc)*(x-xc)));
                    cnt[c]+=row[x].erase(yc-dis,yc+dis);
                }
            }
            else if(op[i].type==1)
            {
                int xc=op[i].data[0];
                int yc=op[i].data[1];
                int r=op[i].data[2];
                int c=op[i].data[3];
                for(int x=max(0,xc-r);x<=min(n-1,xc+r);x++)
                {
                    int dis=r-(x-xc>0?x-xc:-(x-xc));
                    cnt[c]+=row[x].erase(yc-dis,yc+dis);
                }
            }
            else if(op[i].type==2)
            {
                int xc=op[i].data[0];
                int yc=op[i].data[1];
                int l=op[i].data[2];
                int w=op[i].data[3];
                int c=op[i].data[4];
                for(int x=max(0,xc);x<min(n,xc+l);x++)
                {
                    cnt[c]+=row[x].erase(yc,yc+w-1);
                }
            }
            else
            {
                int xc=op[i].data[0];
                int yc=op[i].data[1];
                int w=op[i].data[2];
                int c=op[i].data[3];
                for(int x=max(0,xc);x<min(n,xc+(w+1)/2);x++)
                {
                    int dis=(w-1)/2-(x-xc);
                    cnt[c]+=row[x].erase(yc-dis,yc+dis);
                }
            }
        }
        for(int i=1;i<=9;i++) printf("%d%c",cnt[i],i==9?'\n':' ');
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值