D - Dull Chocolates Gym - 101991D -离散化-前缀和

  •  
  • D - Dull Chocolates

  •  Gym - 101991D 
  • 题意:给定n*m的图有k个white的方块,其余的全为black,问有多少点(i,j)满足从(1,1)到(i,j)
  • 这个矩形区域中white的个数为奇数个。
  • 思路:有k个点,点坐标的大小都在1-1e9之内,但是点的数目较小只有1e3,所以进行离散化只需维护相对大小。
  • 然后把这写个离散化的点构成的图进行二维前缀和维护一下,按照题目定义的矩形区域预处理出每个点所构成的矩形区域的
  • white的个数,因为是计算(1,1)-(n,m)闭区间内的点,所以最后在把离散化的图上加上一个点(n+1,m+1).
  • 然后就是进行计算了,遍历离散化后的图,遍历到white的个数为奇数个得点时进行计算,从一个为奇数的点可以确定一片区域都为合法点,这片区域就是,当前点与下面第一个x轴大于他的点之间的距离*当前点与下面第一个y轴大于他的点之间的距离
  • 所构成的合法矩形区域,这个矩形区域里面的点的个数也就是这个矩形区域的面积,-是自己搞懂的,但还是要感谢第一个实现的人——贾队长tql。
  • #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 1234
    map<int,int>okx;
    map<int,int>oky;
    int dp[maxn][maxn];
    int t,x[maxn];
    int y[maxn],lsx,lsy;
    int prex,prey;
    struct node
    {
        int x,y;
    } a[maxn];
    int main()
    {
    //    freopen("dull.in","r",stdin);
        scanf("%d",&t);
        while(t--)
        {
            ll ans=0,tans,n,m,k;
            okx.clear();
            oky.clear();
            memset(dp,0,sizeof(dp));
            scanf("%lld%lld%lld",&n,&m,&k);
            for(int i=0; i<k; i++)
            {
                scanf("%d%d",&a[i].x,&a[i].y);
                x[i]=a[i].x;
                y[i]=a[i].y;
            }
            sort(x,x+k);
            sort(y,y+k);
            lsx=unique(x,x+k)-x;
            lsy=unique(y,y+k)-y;
            for(int i=0; i<lsx; i++)
                okx[x[i]]=i;
            for(int i=0; i<lsy; i++)
                oky[y[i]]=i;
            for(int i=0; i<k; i++)
                dp[okx[a[i].x]][oky[a[i].y]]=1;
            for(int i=0; i<lsx; i++)
                for(int j=0; j<lsy; j++)
                    if(i==0)dp[i][j]+=dp[i][j-1];
                    else if(j==0)dp[i][j]+=dp[i-1][j];
                    else dp[i][j]+=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]);
            x[lsx]=n+1;
            y[lsy]=m+1;
            for(int i=0; i<lsx; i++)
            {
                prex=x[i];
                for(int j=0; j<lsy; j++)
                {
                    prey=y[j];
                    if(dp[i][j]%2)
                        ans+=(ll)(x[i+1]-prex)*(ll)(y[j+1]-prey);
                }
            }
            tans=(ll)(n*m)-ans;
            printf("%lld %lld\n",ans,tans);
        }
        return 0;
    }
    
  •  
  •  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值