zoj 3540 线段树笔记

Adding New Machine

 

Time Limit: 5 Seconds      Memory Limit: 65536 KB

 

Incredible Crazily Progressing Company (ICPC) suffered a lot with the low speed of procedure. After investigation, they found that the bottleneck was at Absolutely Crowded Manufactory (ACM). In oder to accelerate the procedure, they bought a new machine for ACM. But a new problem comes, how to place the new machine into ACM?

ACM is a rectangular factor and can be divided intoW * H cells. There are N retangular old machines in ACM and the new machine can not occupy any cell where there is old machines. The new machine needsM consecutive cells. Consecutive cells means some adjacent cells in a line. You are asked to calculate the number of ways to choose the place for the new machine.

Input

There are multiple test cases (no more than 50). The first line of each test case contains 4 integersW, H, N, M (1 ≤ W, H ≤ 107, 0 ≤N ≤ 50000, 1 ≤ M ≤ 1000), indicating the width and the length of the room, the number of old machines and the size of the new machine. ThenN lines follow, each of which contains 4 integers Xi1,Yi1, Xi2 and Yi2 (1 ≤Xi1Xi2W, 1 ≤ Yi1Yi2H), indicating the coordinates of the i-th old machine. It is guarantees that no cell is occupied by two old machines.

Output

Output the number of ways to choose the cells to place the new machine in one line.

Sample Input

3 3 1 2
2 2 2 2
3 3 1 3
2 2 2 2
2 3 2 2
1 1 1 1
2 3 2 3

Sample Output

8
4
3

做个笔记

//一个w*h的矩形区域,有若干个互不相交的矩形,现在要把一个1*m的矩形
//放在这个矩形区域,问有多少种方案

//分析:对于每个矩形,如果把它覆盖范围向右延伸m个单位,对于没有覆盖的格子,可以以这个格子为
//右边界放置1*m的矩形,这是横向的情况,纵向的也同理,所以最后答案就是2*w*h-area1-area2
//area1和area2分别是两种情况的矩形面积的并
//特殊情况:m==1时,横向和纵向是一样的,所以最后答案除以2
//很多细节要处理

# include <math.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <algorithm>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <vector>
# include <cstring>
# include <list>
# include <ctime>

# define For(i,a)   for((i)=0;i<(a);(i)++)
# define MAX(x,y)   ((x)>(y)? (x):(y))
# define MIN(x,y)   ((x)<(y)? (x):(y))
# define MEM(a)     (memset((a),0,sizeof(a)))
# define MEME(a)    (memset((a),-1,sizeof(a)))
# define MEMX(a)    (memset((a),0x7f,sizeof(a)))

using namespace std;

typedef long long           ll      ;
typedef unsigned long long  ull     ;
typedef unsigned int        uint    ;
typedef unsigned char       uchar   ;
#define N 111111
struct node
{
    int l,r;
    int cover;
    int sum;
}tree[N<<2];
void build(int i,int l,int r)
{
    tree[i].l=l; tree[i].r=r;
    tree[i].cover=0; tree[i].sum=0;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    build(i+i,l,mid);
    build(i+i+1,mid+1,r);
}
void update(int i,int l,int r,int val,int *a)
{
    if(tree[i].l>=l&&tree[i].r<=r)
    {
        tree[i].cover+=val;
        if(tree[i].cover>0)
            tree[i].sum=a[tree[i].r+1]-a[tree[i].l];
        else  if(tree[i].l==tree[i].r)
            tree[i].sum=0;
        else
            tree[i].sum=tree[i+i].sum+tree[i+i+1].sum;
        return ;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    if(l<=mid)
        update(i+i,l,r,val,a);
    if(r>mid)
        update(i+i+1,l,r,val,a);
    if(tree[i].cover>0)
        tree[i].sum=a[tree[i].r+1]-a[tree[i].l];
    else  if(tree[i].l==tree[i].r)
        tree[i].sum=0;
    else
        tree[i].sum=tree[i+i].sum+tree[i+i+1].sum;
}
struct Node
{
    int val;
    int l,r;
    int in;
}a[N],b[N];
int X[N],Y[N];
bool cmp(Node a,Node b)
{
    return a.val<b.val;
}
int bin(int *a,int left,int right,int key)
{
    while(left<=right)
    {
        int mid=(left+right)>>1;
        if(a[mid]==key)
            return mid;
        else if(a[mid]<key)
            left=mid+1;
        else
            right=mid-1;
    }
    return 0;
}
int main()
{
    int w,h,n,m,i,j;
    int x1,x2,y1,y2,l,r;
    int p,q,pp,qq;
    while(scanf("%d%d%d%d",&w,&h,&n,&m)!=EOF)
    {
        p=q=pp=qq=1;
        a[0].val=1;a[0].in=1;
        a[0].l=1;a[0].r=h+1;
        a[1].val=m;a[1].in=-1;
        a[1].l=1;a[1].r=h+1;

        b[0].val=1;b[0].in=1;
        b[0].l=1;b[0].r=w+1;
        b[1].val=m;b[1].in=-1;
        b[1].l=1;b[1].r=w+1;

        X[p++]=1;X[p++]=h+1;
        Y[q++]=1;Y[q++]=w+1;
        j=2;
        ll sum=(ll)w*(ll)h;
        for(i=0;i<n;i++)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            sum-=(ll)(x2-x1+1)*(ll)(y2-y1+1);
            a[j].val=x1;  a[j+1].val=x2+m;//这个为开区间,方便处理 因为可能出现这样的情况:更新区间[5,6]时,5,6在分别在左右子树
                                          //那么就是更新[5,5]和[6,6].计算这两个区间的测度为2,但是实际上[5,6]的测度可能不是2(因为这是离散过的)
            a[j].l=a[j+1].l=y1;a[j].r=a[j+1].r=y2+1; //这个也为开区间,方便处理
            a[j].in=1;a[j+1].in=-1;

            b[j].val=y1;b[j+1].val=y2+m;
            b[j].l=b[j+1].l=x1;b[j].r=b[j+1].r=x2+1;
            b[j].in=1;b[j+1].in=-1;

            X[p++]=y1;X[p++]=y2+1;
            Y[q++]=x1;Y[q++]=x2+1;
            j+=2;
        }
        if(m==1)
        {
            printf("%lld\n",sum);
            continue;
        }
        sort(a,a+j,cmp);
        sort(b,b+j,cmp);
        sort(X+1,X+p);
        sort(Y+1,Y+q);
        for(i=1;i<p;i++)
            if(X[i]!=X[i-1]) X[pp++]=X[i];
        for(i=1;i<q;i++)
            if(Y[i]!=Y[i-1]) Y[qq++]=Y[i];
        ll ans=2*(ll)w*(ll)h;
        build(1,1,pp-1);
        for(i=0;i<j-1;i++)
        {
            if(a[i].val>w) break;
            y1=a[i].l; y2=a[i].r;
            l=bin(X,1,pp-1,y1); r=bin(X,1,pp-1,y2);
            update(1,l,r-1,a[i].in,X);
            ans-=(ll)(MIN(w+1,a[i+1].val)-a[i].val)*(ll)tree[1].sum;
        }
        build(1,1,qq-1);
        for(i=0;i<j-1;i++)
        {
            if(b[i].val>h) break;
            y1=b[i].l; y2=b[i].r;
            l=bin(Y,1,qq-1,y1); r=bin(Y,1,qq-1,y2);
            update(1,l,r-1,b[i].in,Y);
            ans-=(ll)(MIN(h+1,b[i+1].val)-b[i].val)*(ll)tree[1].sum;
        }
        printf("%lld\n",ans);
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值