HDU 4419-矩形面积并+容斥原理

博客介绍了如何解决HDU 4419问题,通过直接计算每个颜色区域的面积,并利用容斥原理来处理颜色交叠部分,从而得出每个独立区域的面积。博主分享了使用线段树优化的方法,避免了超时,最终实现了400ms内的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


一直想怎么直接处理多个颜色信息,sb了,直接暴力算每种颜色的面积并,再通过容斥原理乱搞计算得到每块的面积即可。



直接开7个大小为N的线段树维护每个颜色会超时,要按每种颜色数量开一个,刚好400ms

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;

const int N =2* 10000+500  ;
struct node
{
    int flag;
    int lx,rx,y,col;
    node() {}
    node(double a,double b,double c,int d,int cc)
    {
        lx=a,rx=b,y=c,flag=d;
        col=cc;
    }
    bool operator<(node b)const
    {
        return y<b.y;
    }
};
node line[N],line22[N];
int X[2*N];
struct tree
{
    long long  sum[4*N];
    long long  add[4*N];
    void build(int l,int r,int rt)
    {
        if(l == r)
        {
            sum[rt]=add[rt]=0;
            return ;
        }
        int m = (l + r) >> 1;
        build(l,m,2*rt);
        build(m+1,r,2*rt+1);
        sum[rt]=add[rt]=0;
    }
    void pushup(int i,int l,int r)
    {
        if (add[i]) sum[i]=X[r+1]-X[l];
        else if (l==r) sum[i]=0;
        else sum[i]=sum[i<<1]+sum[i<<1|1];
    }
    void update(int i, int l, int r, int ql, int qr, int val) 
    {
        if(l > qr || ql > r)        
            return ;
        if(ql<=l&&qr>=r)    
        {
            add[i] += val;
            pushup(i,l,r);
            return ;
        }          
        int mid = (l + r) >> 1;
        update(i << 1, l, mid, ql, qr, val);
        update(i << 1 | 1, mid + 1, r, ql, qr, val);
        pushup(i,l,r);
    }
    void init()
    {
        memset(add,0,sizeof add);
        memset(sum,0,sizeof sum);
    }
    long long cal(node *line,int num)
    {
        if (num==0) return 0;
        //  sort(line+1,line+1+num);
        int cun_x=0;
        for (int i=1; i<=num; i++)
        {
            if (line[i].flag==1)
                X[++cun_x]=line[i].lx,X[++cun_x]=line[i].rx;
        }
        sort(X+1,X+1+cun_x);
        int num_x=unique(X+1,X+1+cun_x)-X-1;
        long long ans=0;
        build(1,num_x,1);
        for (int i=1; i<num; i++)
        {
            int l=lower_bound(X+1,X+1+num_x,line[i].lx)-X;
            int r=lower_bound(X+1,X+1+num_x,line[i].rx)-X-1;
            update(1,1,num_x,l,r,line[i].flag);
            ans+= 1LL*sum[1]*( line[i+1].y-line[i].y);
        }
        return ans;
    }
};
tree tp;
long long  out[8];
long long  ans[8];
int main()
{
    int n  ;
    int cnt=1;
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%d",&n);

        int x1,x2,y1,y2;
        int num=0;
        char s[5];
        for (int i=0; i<n; i++)
        {
            scanf("%s%d%d%d%d",s,&x1,&y1,&x2,&y2);
            int col;
            if (s[0]=='R') col=1;
            if (s[0]=='G') col=2;
            if (s[0]=='B') col=4;
            line[++num]=node(x1,x2,y1,1,col);
            X[num]=x1;
            line[++num]=node(x1,x2,y2,-1,col);
            X[num]=x2;
        }
        sort(line+1,line+1+num);

        ans[7]=tp.cal(line,num);

        int cun=0;
        for (int i=1; i<=num; i++)   if(line[i].col==1)
                line22[++cun]=line[i];
        ans[1]=tp.cal(line22,cun);

        cun=0;
        for (int i=1; i<=num; i++)  if(line[i].col==2)
                line22[++cun]=line[i];
        ans[2]=tp.cal(line22,cun);

        cun=0;
        for (int i=1; i<=num; i++)   if(line[i].col!=4)
                line22[++cun]=line[i];
        ans[3]=tp.cal(line22,cun);

        cun=0;
        for (int i=1; i<=num; i++)   if(line[i].col==4)
                line22[++cun]=line[i];
        ans[4]=tp.cal(line22,cun);

        cun=0;
        for (int i=1; i<=num; i++)   if(line[i].col!=2)
                line22[++cun]=line[i];
        ans[5]=tp.cal(line22,cun);

        cun=0;
        for (int i=1; i<=num; i++)   if(line[i].col!=1)
                line22[++cun]=line[i];
        ans[6]=tp.cal(line22,cun);
 
        printf("Case %d:\n",cnt++); 
        out[1]=ans[7]-ans[6];
        out[2]=ans[7]-ans[5];
        out[4]=ans[7]-ans[3];

        out[3]=ans[7]-out[1]-out[2]-ans[4];
        out[5]=ans[7]-out[1]-out[4]-ans[2];
        out[6]=ans[7]-out[2]-out[4]-ans[1];
        out[7]=ans[7]-out[1]-out[2]-out[3]-out[4]-out[5]-out[6];

        int j;
        j=1;
        printf("%lld\n",out[j]);
        j=2;
        printf("%lld\n",out[j]);
        j=4;
        printf("%lld\n",out[j]);
        j=3;
        printf("%lld\n",out[j]);
        j=5;
        printf("%lld\n",out[j]);
        j=6;
        printf("%lld\n",out[j]);
        j=7;
        printf("%lld\n",out[j]);

    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值