hdoj 4419 Colourful Rectangle 【线段树 + 扫描线】

Colourful Rectangle

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1460    Accepted Submission(s): 593


Problem Description
We use Red, Green and Blue to make new colours. See the picture below:


Now give you n rectangles, the colour of them is red or green or blue. You have calculate the area of 7 different colour. (Note: A region may be covered by same colour several times, but it’s final colour depends on the kinds of different colour)
 

Input
The first line is an integer T(T <= 10), the number of test cases. The first line of each case contains a integer n (0 < n <= 10000), the number of rectangles. Then n lines follows. Each line start with a letter C(R means Red, G means Green, B means Blue) and four integers x1, y1, x2, y2(0 <= x1 < x2 < 10^9, 0 <= y1 < y2 < 10^9), the left-bottom's coordinate and the right-top's coordinate of a rectangle.
 

Output
For each case, output a line "Case a:", a is the case number starting from 1,then 7 lines, each line contain a integer, the area of each colour. (Note: You should print the areas as the order: R, G, B, RG, RB, GB, RGB).
 

Sample Input
  
  
3 2 R 0 0 2 2 G 1 1 3 3 3 R 0 0 4 4 G 2 0 6 4 B 0 2 6 6 3 G 2 0 3 8 G 1 0 6 1 B 4 2 7 7
 

Sample Output
  
  
Case 1: 3 3 0 1 0 0 0 Case 2: 4 4 12 4 4 4 4 Case 3: 0 12 15 0 0 0 0
 

题意:给你n个矩形,有R、G、B三种颜色,问你R、G、B、RG、RB、GB、RGB颜色的面积并。


思路:状态压缩一下,R = 1, G = 2,B = 4。那么RG = R | G......,总状态1-7。PushUp的时候,先手求出区间的状态color。然后求出1-7的状态 | color的线段长度。注意:color的状态可以由0状态得到。


AC代码:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 1000000
#define eps 1e-8
#define MAXN (20000+10)
#define MAXM (100000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
struct Tree{
    int l, r;
    LL sum[8];
    int cover[3];
};
Tree tree[MAXN<<2];
void Build(int o, int l, int r)
{
    tree[o].l = l; tree[o].r = r;
    for(int i = 1; i <= 7; i++) tree[o].sum[i] = 0LL;
    for(int i = 0; i <= 2; i++) tree[o].cover[i] = 0;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    Build(lson); Build(rson);
}
int rec[MAXN];
void PushUp(int o)
{
    int color = 0;
    for(int i = 0; i <= 2; i++) if(tree[o].cover[i])
            color |= (1<<i);
    CLR(tree[o].sum, 0LL);
    for(int i = 1; i <= 7; i++)
        tree[o].sum[i|color] += tree[ll].sum[i] + tree[rr].sum[i];
    LL total = 1LL * (rec[tree[o].r+1] - rec[tree[o].l]);
    for(int i = 1; i <= 7; i++) total -= tree[o].sum[i];
    tree[o].sum[color] += total;
}
void Update(int o, int L, int R, int cover, int op)
{
    if(tree[o].l == L && tree[o].r == R)
    {
        tree[o].cover[op] += cover;
        PushUp(o);
        return ;
    }
    int mid = (tree[o].l + tree[o].r) >> 1;
    if(R <= mid) Update(ll, L, R, cover, op);
    else if(L > mid) Update(rr, L, R, cover, op);
    else {Update(ll, L, mid, cover, op); Update(rr, mid+1, R, cover, op);}
    PushUp(o);
}
struct Node{
    int op, x1, x2, y, cover;
};
Node num[MAXN];
bool cmp(Node a, Node b){
    return a.y < b.y;
}
int get(char op)
{
    if(op == 'R') return 0;
    if(op == 'G') return 1;
    return 2;
}
LL ans[8];
int main()
{
    int t, kcase = 1; Ri(t);
    W(t)
    {
        int n; Ri(n); int top = 0;
        for(int i = 0; i < n; i++)
        {
            int x1, y1, x2, y2;
            char str[10]; Rs(str);
            Ri(x1); Ri(y1); Ri(x2); Ri(y2);
            num[top].x1 = x1; num[top].x2 = x2;
            num[top].y = y1; num[top].cover = 1;
            num[top].op = get(str[0]); rec[top++] = x1;

            num[top].x1 = x1; num[top].x2 = x2;
            num[top].y = y2; num[top].cover = -1;
            num[top].op = get(str[0]); rec[top++] = x2;
        }
        sort(num, num+top, cmp); sort(rec, rec+top);
        int N = unique(rec, rec+top) - rec;
        Build(1, 0, N-1); CLR(ans, 0LL);
        int l = lower_bound(rec, rec+N, num[0].x1) - rec;
        int r = lower_bound(rec, rec+N, num[0].x2) - rec;
        Update(1, l, r-1, num[0].cover, num[0].op);
        for(int i = 1; i < top; i++)
        {
            l = lower_bound(rec, rec+N, num[i].x1) - rec;
            r = lower_bound(rec, rec+N, num[i].x2) - rec;
            for(int j = 1; j <= 7; j++)
                ans[j] += tree[1].sum[j] * (num[i].y - num[i-1].y);
            if(l <= r-1) Update(1, l, r-1, num[i].cover, num[i].op);
        }
        printf("Case %d:\n", kcase++); swap(ans[3], ans[4]);
        for(int i = 1; i <= 7; i++) Pl(ans[i]);
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值