Dull Chocolates Gym - 101991D ——树状数组

Input file: dull.in
Output file: standard output
Time limit: 9 seconds
Memory limit: 1024 megabytes
Fouad wants to eat a chocolate bar, so he bought a rectangular chocolate bar that has N rows and M
columns of chocolate.
Fouad found that most of the cells in that chocolate bar are dark chocolate except for K cells which are
white chocolate. Now, he wants to eat a prefix sub-grid of the bar. A prefix sub-grid is a rectangular
sub-grid that starts at the first cell (1, 1) and ends at any cell (i, j). Fouad is also wondering how many
perfect prefix sub-grids of the bar. A perfect prefix sub-grid is a one that contains an odd number of white
chocolate cells.
Help Fouad find the number of perfect prefix sub-grids and non-perfect prefix sub-grids.
Input
The first line of the input containing a single integer T specifying the number of test cases.
Each test case begins with a line containing three integers N, M, and K (1 ≤ N, M ≤ 109
, 0 ≤ K ≤ 103
),
in which N and M are the number of rows and columns in the chocolate bar, respectively, and K is the
number of white chocolate cells.
Then K lines follow, each line containing two integers Xi and Yi (1 ≤ Xi ≤ N, 1 ≤ Yi ≤ M), giving the
positions of the white chocolate cells. It is guaranteed that all the given positions are unique.
Output
For each test case, print a single line containing two space-separated integers representing the number of
perfect prefix sub-grids and non-perfect prefix sub-grids, respectively.
Example
dull.in standard output
3
3 3 0
3 3 1
2 2
5 5 5
1 5
2 1
3 3
4 2
5 4
0 9
4 5
14 11
Note
In the second test case, the chocolate bar can be represented as follows:
ddd
dwd
ddd
in which ‘d’ represents dark chocolate cells while ‘w’ represents white chocolate cells. There are four perfect
prefix sub-grids that end at cells: (2, 2), (2, 3), (3, 2), and (3, 3).

题意:

给你矩形坐标和n个点的坐标,问你有多少以1,1为起始的矩形包含奇数个点。

题解:

可以看到数据范围很小,那么可以用n^2来做,首先设立实点和虚点,比如1,1 和2,2,实点就是这两个,虚点就是1,2和2,1。因为这样能包含所有情况,在x或者y不越过任意虚点的时候答案是不会变的。在求出当前点为右上角的矩形的时候,找出下一个x和y表示这种状态最大能维持到哪个矩形,1,1 3,1的时候,在y=1时x从1到(3-1)都是一个状态。在x和y是边界的时候,就是说x在右边没有点,y上面没有点时特判。首先离散化,否则会出错,比如说x的集合是1,1,3的时候,不离散化得出的答案会被重复算。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e3+5;
int num[N];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x)
{
    for(int i=x;i<N;i+=lowbit(i))
        num[i]++;
}
int query(int x)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=num[i];
    return ans;
}
int x[N],y[N],lsx[N],lsy[N],vis[N][N];
int main()
{
    freopen("dull.in","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(num,0,sizeof(num));
        memset(vis,0,sizeof(vis));
        int n,m,k;
        ll ans=0;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=k;i++)
            scanf("%d%d",&x[i],&y[i]),lsx[i]=x[i],lsy[i]=y[i];
        sort(lsx+1,lsx+1+k),sort(lsy+1,lsy+1+k);
        int allx,ally;
        allx=unique(lsx+1,lsx+1+k)-lsx-1;
        ally=unique(lsy+1,lsy+1+k)-lsy-1;
        for(int i=1;i<=k;i++)
        {
            x[i]=lower_bound(lsx+1,lsx+1+allx,x[i])-lsx;
            y[i]=lower_bound(lsy+1,lsy+1+ally,y[i])-lsy;
            vis[x[i]][y[i]]=1;
        }
        sort(x+1,x+k+1),sort(y+1,y+1+k);
        allx=unique(x+1,x+k+1)-x-1;
        ally=unique(y+1,y+1+k)-y-1;
        for(int i=1;i<=allx;i++)
        {
            for(int j=1;j<=ally;j++)
            {
                if(vis[x[i]][y[j]])
                    add(y[j]);
                int sum=query(y[j]);
                if(sum%2)
                {
                    if(i==allx&&j==ally)
                        ans+=(ll)(n-lsx[x[i]]+1)*(m-lsy[y[j]]+1);
                    else if(i==allx)
                        ans+=(ll)(n-lsx[x[i]]+1)*(lsy[y[j+1]]-lsy[y[j]]);
                    else if(j==ally)
                        ans+=(ll)(lsx[x[i+1]]-lsx[x[i]])*(m-lsy[y[j]]+1);
                    else
                        ans+=(ll)(lsx[x[i+1]]-lsx[x[i]])*(lsy[y[j+1]]-lsy[y[j]]);
                }
            }
        }
        printf("%lld %lld\n",ans,(ll)n*m-ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值