UVA - 1493 Draw a Mess

任务统计

工作日五道题(1/5)

出题人在哪?出来我把你打一顿!

这题说三角形的底边长度一定是奇数
但是数据是有偶数的
我从下午十点调试到晚上一点半
我现在只想把出题人打一顿

链接

https://vjudge.net/problem/UVA-1493

题解

首先一看到覆盖,就想到倒过来离线做
首先我可以枚举每一列
然后就是涂色问题了,一种很好的并查集做法就是把涂过色的区域并起来,维护这个区域的上下端点,每次就可以直接跳过这个区域,由于每个点只会被涂一次,所以花在涂色上的均摊时间为 O ( n m ) O(nm) O(nm)
总的复杂度是 O ( n m + q n ) O(nm+qn) O(nm+qn)

代码

#include <bits/stdc++.h>
#define maxn 210
#define maxm 50010
#define sqr(x) ((x)*(x))
#define code(x,y)  ((x)*M+(y))
using namespace std;
typedef long long ll;
ll N, M, Q, col[maxn*maxm], xc, yc, r, c, l, w, type, p[maxm][5], Xc[maxm], Yc[maxm];
char s[maxm][20];
ll read(ll x=0)
{
    ll c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return f*x;
}
struct ufset
{
    ll f[maxn*maxm], up[maxn*maxm], down[maxn*maxm], done[maxn*maxm];
    void init(ll n)
    {
        for(auto i=0;i<n;i++)f[i]=i, up[i]=down[i]=i%M, done[i]=false;
    }
    ll find(ll x){return x==f[x]?x:f[x]=find(f[x]);}
    void merge(ll x, ll y)
    {
        auto fx=find(x), fy=find(y);
        up[fy]=max(up[fx],up[fy]);
        down[fy]=min(down[fx],down[fy]);
        f[fx]=fy;
    }
}ufs;
bool judge(ll x, ll y)
{
    if(x<0 or x>=N or y<0 or y>=M)return false;
    switch(type)
    {
        case 'D':
            return abs(x-xc) + abs(y-yc) <= r;
        case 'C':
            return sqr(x-xc) + sqr(y-yc) <= sqr(r);
        case 'R':
            return xc<=x and x<=xc+l-1 and yc<=y and y<=yc+w-1;
        case 'T':
            return abs(x-xc) + abs(y-yc) <= (w-1>>1) and x>=xc;
    }
}
void paint(ll id)
{
    ll i, j;
    xc=Xc[id], yc=Yc[id], type=s[id][0];
    switch(type)
    {
        case 'D':
            r=p[id][1], c=p[id][2];
            break;
        case 'C':
            r=p[id][1], c=p[id][2];
            break;
        case 'R':
            l=p[id][1], w=p[id][2], c=p[id][3];
            break;
        case 'T':
            w=p[id][1], c=p[id][2];
            break;
    }
    for(i=0;i<N;i++)
    {
        j=ufs.down[ ufs.find( code(i,yc) ) ];
        while(judge(i,j))
        {
            if(ufs.done[ code(i,j) ]==false)
            {
                col[ code(i,j) ]=c;
                ufs.done[ code(i,j) ]=true;
                if(j>0 and ufs.done[ code(i,j-1) ] )ufs.merge( code(i,j) , code(i,j-1) );
                if(j<M-1 and ufs.done[ code(i,j+1) ] )ufs.merge( code(i,j) , code(i,j+1) );
            }
            if(j==0)break;
            j=ufs.down[ ufs.find( code(i,j-1) ) ];
        }

        j=ufs.up[ ufs.find( code(i,yc) )];
        while(judge(i,j))
        {
            if(ufs.done[ code(i,j) ]==false)
            {
                col[ code(i,j) ]=c;
                ufs.done[ code(i,j) ]=true;
                if(j>0 and ufs.done[ code(i,j-1) ] )ufs.merge( code(i,j) , code(i,j-1) );
                if(j<M-1 and ufs.done[ code(i,j+1) ] )ufs.merge( code(i,j) , code(i,j+1) );
            }
            if(j==M-1)break;
            j=ufs.up[ ufs.find( code(i,j+1) ) ];
        }
    }
}
int main()
{
    ll ans[10], i, j;
    while( ~scanf("%lld%lld%lld",&N,&M,&Q) )
    {
        ufs.init(N*M);
        for(i=1;i<=Q;i++)
        {
            scanf("%s",s[i]);
            Xc[i]=read(), Yc[i]=read();
            for(j=1;j<=(s[i][0]=='R'?3:2);j++)p[i][j]=read();
        }
        for(i=0;i<N*M;i++)col[i]=0;
        for(i=Q;i;i--)paint(i);
        memset(ans,0,sizeof(ans));
        for(i=0;i<N*M;i++)ans[col[i]]++;
        for(i=1;i<=9;i++)printf("%lld",ans[i]), putchar(i==9?10:32);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值