hdu 4056 Draw a Mess -并查集+滑动法

来源:互联网 发布:php curl 输出图片 编辑:程序博客网 时间:2024/05/02 02:23

http://acm.hdu.edu.cn/showproblem.php?pid=4056


题意:给n*m的格点 (n=200,m=5e5)

q次操作,每次按 四个几何图形 的面积去覆盖格点 ,每个图形带有一个颜色C (q=5e5,C=[1-9])

问最后q次操作完成后,每种颜色的格子有多少个,输出9个数


可以知道,颜色会覆盖,因此,从最后面开始处理,如果当前要涂色的格子未涂色,则这个格子最终必定是当前要涂的色,同理如果当前格子已经有色,则需要忽略。


现在问题是怎么处理涂色操作?

   由于行很少,可以暴力按行涂色,也即把该几何图形要覆盖的每一行都遍历,对于每行,用并查集去维护一个 大小为M的列:


维护一个father数组,fa[x]指的是x这个位置起,到达下一个可被涂色的位置-1,

维护一个vis数组,vis[x]=1,表示该位置已经涂色,=0则未涂色


假如图形X在 第i行的涂色范围是第L列到第R列,则

l=max (l,0);                r=min(r,m-1);                int fx=find(l);                for (int i=r; i>=l;)                {                    int fy=find(i);<span style="white-space:pre"></span>//找到最左的可涂色位置                    if (!vis[fy]) ans[col]++;<span style="white-space:pre"></span>//可涂色                    vis[fy]=1;<span style="white-space:pre"></span>//标记已涂色                    if (fx!=fy) fa[fy]=fx;<span style="white-space:pre"></span>//更新 【最左可涂色位置】                    i=fy-1;<span style="white-space:pre"></span>//继续滑动                }



#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <map>#include <set>#include <vector>#include <iostream>using namespace std;const double pi=acos(-1.0);double eps=0.000001;int fa[51234];int vis[51234];int find(int x){    if (fa[x]==x)        return x;    else return fa[x]=find(fa[x]);}struct node{    char op[12];    int x,y,z,d;    int e;    node() {}};node tm[51234];int ans[10];int main(){    int n,m,k;    while(scanf("%d%d%d",&n,&m,&k)!=EOF)    {        memset(ans,0,sizeof ans);        for (int i=1; i<=k; i++)        {            scanf("%s%d%d%d%d",tm[i].op,&tm[i].x,&tm[i].y,&tm[i].z,&tm[i].d);            if (tm[i].op[0]=='R') scanf("%d",&tm[i].e);        }        for (int j=0; j<n; j++)        {            for (int i=0; i<=m; i++) fa[i]=i,vis[i]=0;            for (int i=k; i>=1; i--)            {                int l,r,col=tm[i].d;                if (tm[i].op[0]=='C')                {                    int up=tm[i].x+tm[i].z;                    int down=tm[i].x-tm[i].z;                    if (!(j>=down&&j<=up ))continue;                    int tmp=tm[i].z*tm[i].z-(tm[i].x-j)*(tm[i].x-j);                    tmp=sqrt(tmp);                    l=tm[i].y-tmp;                    r=tm[i].y+tmp;                }                if (tm[i].op[0]=='D')                {                    int up=tm[i].x+tm[i].z;                    int down=tm[i].x-tm[i].z;                    if (!(j>=down&&j<=up ))continue;                    l=tm[i].z-abs(j-tm[i].x);                    r=tm[i].y+l;                    l=tm[i].y-l;                }                if (tm[i].op[0]=='R')                {                    col=tm[i].e;                    int up=tm[i].x+tm[i].z-1;                    int down=tm[i].x;                    if (!(j>=down&&j<=up ))continue;                    l=tm[i].y;                    r=tm[i].y+tm[i].d-1;                }                if (tm[i].op[0]=='T')                {                    int up=tm[i].x+(tm[i].z+1)/2-1;                    int down=tm[i].x;                    if (!(j>=down&&j<=up ))continue;                    int tmp=(tm[i].z-1)/2+(tm[i].x-j);                    l=tm[i].y-tmp;                    r=tm[i].y+tmp;                }                l=max (l,0);                r=min(r,m-1);                int fx=find(l);                for (int i=r; i>=l;)                {                    int fy=find(i);                    if (!vis[fy]) ans[col]++;                    vis[fy]=1;                    if (fx!=fy) fa[fy]=fx;                    i=fy-1;                }            }        }        for (int i=1; i<=9; i++)        {            if (i>1) printf(" ");            printf("%d",ans[i]);        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击