hdu4056Draw a Mess(线段树解法)

来源:互联网 发布:淘宝特卖会 编辑:程序博客网 时间:2024/05/22 19:27

题目请戳这里

题目大意:给一个n*m的矩形,有9中颜色,4种集合图形,q个操作,每个操作是将矩形中指定位置的某种几何形状的格子染相应的颜色。求最后9种颜色相应的数量。

题目分析:第一眼感觉就是线段树,一开始想的是写个二维的线段树,然后就在想怎么更新比较快。发现二维线段树除了更新矩形外对于其他3个图形的更新毫无优势。如果一行一行的更新,太慢了。一直在纠结怎样快速成段更新其他3种几何图像。最后1个小时决定敲一下,敲了一会也放弃了。还好没有继续敲。

这题官方题解给的是O(n*m)的线性做法。不过线段树也是可以做的。只是要写n棵线段树,而不是二维的!!其实写n棵线段树也容易爆内存的,何况二维的。再考虑到每次对一个格子涂色后就会覆盖上一次的颜色,所以每个格子最终的颜色取决于最后一次涂的颜色。所以要把查询倒着做!!涂过颜色的格子就删掉。这样线段树就比较容易完成了。不过效率并不是十分高,踩线过。。

唉,2道线段树,一道都没出,到现在了,还是这么弱啊。。。

详情请见代码:

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int N = 201;const int M = 50001;struct nd{    char c;    int p[5];}ask[M];int m,n,q;int ans[11];struct segt{    short int tree[M<<2];    void init(int num,int s,int e)    {        if(s == e)        {            tree[num] = 1;            return;        }        int mid = (s + e)>>1;        init(num<<1,s,mid);        init(num<<1|1,mid + 1,e);        tree[num] = tree[num<<1] + tree[num<<1|1];    }    int query(int num,int s,int e,int l,int r)    {        if(s == l && e == r)            return tree[num];        if(tree[num] == 0)            return 0;        int mid = (s + e)>>1;        if(r <= mid)            return query(num<<1,s,mid,l,r);        else        {            if(l > mid)                return query(num<<1|1,mid + 1,e,l,r);            else                return query(num<<1,s,mid,l,mid) + query(num<<1|1,mid + 1,e,mid + 1,r);        }    }    void insert(int num,int s,int e,int l,int r)    {        if(s == l && e == r)        {            tree[num] = 0;            return;        }        if(tree[num] == 0)            return;        int mid = (s + e)>>1;        if(r <= mid)            insert(num<<1,s,mid,l,r);        else        {            if(l > mid)                insert(num<<1|1,mid + 1,e,l,r);            else            {                insert(num<<1,s,mid,l,mid);                insert(num<<1|1,mid + 1,e,mid + 1,r);            }        }        tree[num] = tree[num<<1] + tree[num<<1|1];    }}lcm[N];void Circle(int id){    int i,l,r;    for(i = ask[id].p[0] + 1 - ask[id].p[2];i <= ask[id].p[0] + 1 + ask[id].p[2];i ++)    {        if(i < 1)            continue;        if(i > n)            break;        int tmp = (int)sqrt((double)(ask[id].p[2] * ask[id].p[2] - (i - ask[id].p[0] - 1) * (i - ask[id].p[0] - 1)));        l = ask[id].p[1] + 1 - tmp;        r = ask[id].p[1] + 1 + tmp;        if(l < 1)            l = 1;        if(r > m)            r = m;        if(l > r)            continue;        tmp = lcm[i].query(1,1,m,l,r);        if(tmp)        {            ans[ask[id].p[3]] += tmp;            lcm[i].insert(1,1,m,l,r);        }    }}void Diamond(int id){    int i,l,r;    for(i = ask[id].p[0] + 1 - ask[id].p[2];i <= ask[id].p[0] + 1 + ask[id].p[2];i ++)    {        if(i < 1)            continue;        if(i > n)            break;        l = ask[id].p[1] + 1 - ask[id].p[2] + abs(i - ask[id].p[0] - 1);        r = ask[id].p[1] + 1 + ask[id].p[2] - abs(i - ask[id].p[0] - 1);        if(l < 1)            l = 1;        if(r > m)            r = m;        if(l > r)            continue;        int tmp = lcm[i].query(1,1,m,l,r);        if(tmp)        {            ans[ask[id].p[3]] += tmp;            lcm[i].insert(1,1,m,l,r);        }    }}void Triangle(int id){    int i,l,r;    int h = (ask[id].p[2] + 1)>>1;    int cnt = 0;    for(i = ask[id].p[0] + h;i >= ask[id].p[0] + 1;i --,cnt ++)    {        if(i > n)            continue;        l = ask[id].p[1] + 1 - cnt;        r = ask[id].p[1] + 1 + cnt;        if(l < 1)            l = 1;        if(r > m)            r = m;        int tmp = lcm[i].query(1,1,m,l,r);        if(tmp)        {            ans[ask[id].p[3]] += tmp;            lcm[i].insert(1,1,m,l,r);        }    }}void Rectangle(int id){    int i,l,r;    l = ask[id].p[1] + 1;    r = ask[id].p[1] + ask[id].p[3];    if(l > r)        return;    if(r > m)        r = m;    for(i = ask[id].p[0] + 1;i <= ask[id].p[0] + ask[id].p[2];i ++)    {        if(i > n)            break;        int tmp = lcm[i].query(1,1,m,l,r);        if(tmp)        {            ans[ask[id].p[4]] += tmp;            lcm[i].insert(1,1,m,l,r);        }    }}char op[12];int main(){    int i;    while(scanf("%d",&n) != EOF)    {        scanf("%d%d",&m,&q);        for(i = 1;i <= n;i ++)            lcm[i].init(1,1,m);        memset(ans,0,sizeof(ans));        for(i = 1;i <= q;i ++)        {            scanf("%s",op);            ask[i].c = op[0];            for(int j = 0;j < 4;j ++)                scanf("%d",&ask[i].p[j]);            if(*op == 'R')                scanf("%d",&ask[i].p[4]);        }        for(i = q;i >= 1;i --)        {            switch(ask[i].c)            {            case 'C':Circle(i);break;            case 'D':Diamond(i);break;            case 'T':Triangle(i);break;            case 'R':Rectangle(i);break;            }        }        for(i = 1;i < 9;i ++)            printf("%d ",ans[i]);        printf("%d\n",ans[i]);    }    return 0;}//4484MS53624K


原创粉丝点击