矩形面积k次交 UVA - 11983

算是模板题,会了面积交这个应该就会了,正常面积交分为覆盖1次以上,两次以上,这个就分为覆盖1到k次以上就行了。

这个题有点边界问题:是让你求覆盖的点,所以你可以假设一个1*1的正方向表示它的左下角被覆盖,那你读入x2,y2时就让x2++,y2++。这样直接算面积就处理好边界了。

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define ls num*2
#define rs num*2+1
using namespace std;

const int maxn = 3e5 + 1010;
int k;
ll loc[maxn*2];
struct seg{
    ll l, r, h;
    int flag;
    bool operator < (const seg &a)const{
        return h < a.h;
    }
}line[maxn*2];

struct node{
    ll l, r, sum;
    ll len[12];

}p[maxn*4];

void build(int num, int l, int r){
    p[num] = (node){l, r, 0, 0};
    if(l == r) return;
    int mid = (l+r)/2;
    build(ls, l, mid);
    build(rs, mid+1, r);
}

void pushup(int num){
    ll int x = p[num].sum;
    ll l = p[num].l, r = p[num].r;
    if(p[num].sum){
        for(int i = 1; i <= k; i++){
            if(p[num].sum >= i) p[num].len[i] = loc[r+1] - loc[l];
            else if(l == r) p[num].len[i] = 0;
            else p[num].len[i] = p[ls].len[i-x] + p[rs].len[i-x];
        }
    }
    else{
        for(int i = 1; i <= k; i++){
            if(l == r) p[num].len[i] = 0;
            else p[num].len[i] = p[ls].len[i] + p[rs].len[i];
        }
    }
}

void change(int num, ll ul, ll ur, int x){
    ll l = p[num].l, r = p[num].r;
    if(loc[r+1] <= ul || loc[l] >= ur) return;
    if(loc[r+1] <= ur && loc[l] >= ul){
        p[num].sum += x;
        pushup(num);
        return;
    }
    change(ls, ul, ur, x);
    change(rs, ul, ur, x);
    pushup(num);
}

int main(){
    ll x1, x2, y1, y2, n, pos;
    int cas = 0;
    int t; scanf("%d",&t);
    while(t--){
        pos = 0;
        scanf("%lld %d",&n,&k);
        rep(i, 1, n){
            scanf("%lld%lld%lld%lld",&x1, &y1, &x2, &y2);
            x2++, y2++;
            loc[++pos] = x1;
            line[pos] = (seg){x1, x2, y1, 1};
            loc[++pos] = x2;
            line[pos] = (seg){x1, x2, y2, -1};
        }
        n *= 2;
        sort(line+1, line+1+n);
        sort(loc+1, loc+1+n);
        int num = unique(loc+1, loc+1+n) - loc - 1;
        build(1, 1, num-1);
        ll ans = 0;
        rep(i, 1, n-1){
            change(1, line[i].l, line[i].r, line[i].flag);
            ans += p[1].len[k] * (line[i+1].h - line[i].h);
        }
        printf("Case %d: %lld\n",++cas, ans);
    }
    return 0;
}

 

posted @ 2019-12-03 15:47  philo_zhou  阅读(255)  评论(0编辑  收藏  举报