hdu 4419 Colourful Rectangle(矩形面积并)


题意:给出红绿蓝三种颜色的矩形,某些元素重叠之后会组合成其它颜色,问7种颜色的面积分别为多少。


解法:考虑只有两种颜色AB,那么求A颜色矩形的面积并x,B颜色矩形的面积并为y,AB颜色矩形的面积并为z,则最终,AB颜色的面积为x+y-z,A颜色的面积为x-(x+y-z),B颜色的面积为y-(x+y-z);

类似得,考虑三种颜色:

根据公式先求出三种颜色混和的面积x,然后依次只考虑两种只有两种颜色,求出RG,RB,GB后减去x,分别得到两种颜色混合的面积,然后再求出只有一种颜色的面积。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 20010;
int hash[maxn];
struct node {
    int left, right, key;
    long long sum;
    void init(int l, int r) {
        left = l;
        right = r;
        key=0;
        sum=0;
    }
    int mid() {
        return (left + right) >> 1;
    }
    int length() {
        return hash[right+1] - hash[left];
    }
};
struct SegTree {
    node tree[maxn * 4];
    void init(int l, int r, int idx) {
        tree[idx].init(l, r);
        if (l == r)
            return;
        int mid = tree[idx].mid();
        init(l, mid, idx << 1);
        init(mid + 1, r, (idx << 1) | 1);
    }
    void pushup(int idx) {
        if (tree[idx].key > 0)
            tree[idx].sum=tree[idx].length();
        else {
            if (tree[idx].left == tree[idx].right)
                tree[idx].sum = 0;
            else
                tree[idx].sum = tree[idx << 1].sum + tree[(idx << 1) | 1].sum;
        }
    }
    void update(int left, int right, int idx, int v) {
        if (tree[idx].left >= left && tree[idx].right <= right) {
            tree[idx].key += v;
            pushup(idx);
            return;
        }
        int mid = tree[idx].mid();
        if (left <= mid)
            update(left, right, idx << 1, v);
        if (right > mid)
            update(left, right, (idx << 1) | 1, v);
        pushup(idx);
    }
};
struct edge {
    int type, color;
    int s, t, x;
    void init(int c, int x, int s, int t, int type) {
        color = c;
        this->x = x;
        this->s = s;
        this->t = t;
        this->type = type;
    }
    bool operator <(const edge oth) const {
        return x < oth.x || (x == oth.x && type > oth.type);
    }
};
SegTree st;
edge ed[maxn];
map<int, int> mp;
int n, cnt;
void init() {
    mp.clear();
    int a, b, c, d, k;
    char ch[10];
    scanf("%d",&n);
    for (int i = 1; i <= n; i++) {
        scanf("%s%d%d%d%d", ch, &a, &b, &c, &d);
        if (ch[0] == 'R')
            k = 0;
        else if (ch[0] == 'G')
            k = 1;
        else
            k = 2;
        ed[i].init(k, a, b, d, 1);
        ed[n + i].init(k, c, b, d, -1);
        mp[b] = 0;
        mp[d] = 0;
    }
    sort(ed + 1, ed + n * 2 + 1);
    cnt = 0;
    for (map<int, int>::iterator it = mp.begin(); it != mp.end(); it++){
        (*it).second = ++cnt;
        hash[cnt]=(*it).first;
    }
}
bool flag[3];
void set(int a, int b, int c) {
    flag[0] = a;
    flag[1] = b;
    flag[2] = c;
}
long long get() {
    long long ans = 0;
    st.init(1, cnt - 1, 1);
    int i = 1;
    while (i<=2*n&&!flag[ed[i].color])
        i++;
    if(i>2*n)
        return 0;
    st.update(mp[ed[i].s], mp[ed[i].t] - 1, 1, ed[i].type);
    int pre=ed[i].x;
    i++;
    for (; i <= n * 2; i++) {
        if (!flag[ed[i].color])
            continue;
        ans += st.tree[1].sum * (ed[i].x - pre);
        pre=ed[i].x;
        st.update(mp[ed[i].s], mp[ed[i].t] - 1, 1, ed[i].type);
    }
    return ans;
}
long long ans[10];//R G B RG RB GB RGB
void work() {
    set(1, 0, 0);
    ans[1] = get();//R
    set(0, 1, 0);
    ans[2] = get();//G
    set(0, 0, 1);
    ans[3] = get();//B
    set(1, 1, 1);
    long long all = get();
    set(1, 1, 0);
    long long ab = ans[1] + ans[2] - get();
    set(1, 0, 1);
    long long ac = ans[1] + ans[3] - get();
    set(0, 1, 1);
    long long bc = ans[3] + ans[2] - get();
    ans[7]=all-ans[1]-ans[2]-ans[3]+ab+ac+bc;
    ans[4]=ab-ans[7];
    ans[5]=ac-ans[7];
    ans[6]=bc-ans[7];
    ans[1]=ans[1]-ans[4]-ans[5]-ans[7];
    ans[2]=ans[2]-ans[4]-ans[6]-ans[7];
    ans[3]=ans[3]-ans[5]-ans[6]-ans[7];
}
int main() {
    int cas;
    scanf("%d",&cas);
    for(int c=1;c<=cas;c++){
        init();
        work();
        printf("Case %d:\n",c);
        for(int i=1;i<=7;i++)
            printf("%I64d\n",ans[i]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值