HDU 4419 Colourful Rectangle 线段树求矩阵的并升级版again

题意:有R G B三种颜色的矩形并在一起,两两颜色和三种颜色一起可以搞出另外4中颜色,问最终所有7种面积和为多少。

题解:y轴离散化,x轴扫描,线段树区间维护7种颜色的有效长度。具体来说:首先不考虑区间的lazy,求出区间7种颜色有效长度,然后考虑lazy,

         拿区间 R lazy举例,R 可以把无色染成R ,G染成RG,B染成RB,GB染成RGB,B G lazy做做相同转化即可。


Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
using namespace std;
const int maxn = 10002;
struct line
{
    int x,down,up;
    int left;
    bool operator < (const line &other) const
    {
        if(x == other.x) return left > other.left;
        return x < other.x;
    }
}vertical_line[maxn << 1];
struct node
{
    int l,r;
    __int64 len[8];
    int lazy[4];
}seg[maxn << 3];
int yy[maxn << 1];
__int64 area[8];
int n,top,tot;

inline int ABS(int x)
{
    return x >= 0 ? (x) : (-x);
}

void addmatrix(char c,int x1,int y1,int x2,int y2)
{
    int t;
    if(c == 'R') t = 1;
    else if(c == 'G') t = 2;
    else t = 3;
    vertical_line[tot].x = x1;
    vertical_line[tot].down = y1;
    vertical_line[tot].up = y2;
    vertical_line[tot].left = t;
    tot++;

    vertical_line[tot].x = x2;
    vertical_line[tot].down = y1;
    vertical_line[tot].up = y2;
    vertical_line[tot].left = -t;
    tot++;
    return;
}

void read()
{
    top = tot = 0;
    char str[3];
    int x1,x2,y1,y2;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s %d %d %d %d ",str,&x1,&y1,&x2,&y2);
        yy[top++] = y1;
        yy[top++] = y2;
        addmatrix(str[0],x1,y1,x2,y2);
    }
    sort(vertical_line , vertical_line + tot);
    sort(yy , yy + top);
    top = unique(yy , yy + top) - yy;
    return;
}

void biuld(int l,int r,int num)
{
    seg[num].l = l;
    seg[num].r = r;
    seg[num].len[0] = 1LL * (yy[r] - yy[l]);
    for(int i=1;i<=7;i++)
    {
        if(i <= 3) seg[num].lazy[i] = 0;
        seg[num].len[i] = 0LL;
    }
    if(l + 1 == r) return;
    int mid = (l + r) >> 1;
    biuld(l , mid , num << 1);
    biuld(mid , r , num << 1 | 1);
    return;
}

void UP(int num)
{
    __int64 sum = 0;
    for(int i=0;i<=7;i++)
    {
        if(seg[num].l + 1 == seg[num].r)
        {
            seg[num].len[i] = 0LL;
        }
        else
        {
            seg[num].len[i] = seg[num << 1].len[i] + seg[num << 1 | 1].len[i];
        }
        if(i) sum += seg[num].len[i];
    }
    seg[num].len[0] = 1LL * (yy[seg[num].r] - yy[seg[num].l]) - sum;
    int tmp;
    if(seg[num].lazy[1] > 0)
    {
        tmp = seg[num].len[0];
        seg[num].len[0] = 0;
        seg[num].len[1] += tmp;

        tmp = seg[num].len[2];
        seg[num].len[2] = 0;
        seg[num].len[4] += tmp;

        tmp = seg[num].len[3];
        seg[num].len[3] = 0;
        seg[num].len[5] += tmp;

        tmp = seg[num].len[6];
        seg[num].len[6] = 0;
        seg[num].len[7] += tmp;
    }
    if(seg[num].lazy[2] > 0)
    {
        tmp = seg[num].len[0];
        seg[num].len[0] = 0;
        seg[num].len[2] += tmp;

        tmp = seg[num].len[1];
        seg[num].len[1] = 0;
        seg[num].len[4] += tmp;

        tmp = seg[num].len[3];
        seg[num].len[3] = 0;
        seg[num].len[6] += tmp;

        tmp = seg[num].len[5];
        seg[num].len[5] = 0;
        seg[num].len[7] += tmp;
    }
    if(seg[num].lazy[3] > 0)
    {
        tmp = seg[num].len[0];
        seg[num].len[0] = 0;
        seg[num].len[3] += tmp;

        tmp = seg[num].len[1];
        seg[num].len[1] = 0;
        seg[num].len[5] += tmp;

        tmp = seg[num].len[2];
        seg[num].len[2] = 0;
        seg[num].len[6] += tmp;

        tmp = seg[num].len[4];
        seg[num].len[4] = 0;
        seg[num].len[7] += tmp;
    }
    return;
}

void update(int l,int r,int num,int val)
{
    if(l == seg[num].l && r == seg[num].r)
    {
        seg[num].lazy[ABS(val)] += val;
        UP(num);
        return;
    }
    int mid = (seg[num].l + seg[num].r) >> 1;
    if(mid >= r) update(l , r , num << 1 , val);
    else if(l >= mid) update(l , r , num << 1 | 1 , val);
    else
    {
        update(l , mid , num << 1 , val);
        update(mid , r , num << 1 | 1 , val);
    }
    UP(num);
    return;
}

void addline(int i)
{
    int bjd = lower_bound(yy , yy + top , vertical_line[i].down) - yy;
    int bju = lower_bound(yy , yy + top , vertical_line[i].up) - yy;
    if(bjd != bju) update(bjd , bju , 1 , vertical_line[i].left);
    return;
}

void solve()
{
    memset(area,0,sizeof(area));
    addline(0);
    for(int i=1;i<tot;i++)
    {
        for(int j=1;j<=7;j++)
        {
            area[j] += seg[1].len[j] * (vertical_line[i].x - vertical_line[i-1].x);
        }
        addline(i);
    }
    for(int i=1;i<=7;i++)
    {
        printf("%I64d\n",area[i]);
    }
    return;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    for(int i=1;i<=cas;i++)
    {
        printf("Case %d:\n",i);
        read();
        biuld(0,top-1,1);
        solve();
    }
    return 0;
}


你可能感兴趣的:(HDU 4419 Colourful Rectangle 线段树求矩阵的并升级版again)