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);
    }
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章