Glass Carving CodeForces - 527C (线段树)

C. Glass Carving
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm  ×  h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understanding of what to carve and how.

In order not to waste time, he decided to practice the technique of carving. To do this, he makes vertical and horizontal cuts through the entire sheet. This process results in making smaller rectangular fragments of glass. Leonid does not move the newly made glass fragments. In particular, a cut divides each fragment of glass that it goes through into smaller fragments.

After each cut Leonid tries to determine what area the largest of the currently available glass fragments has. Since there appear more and more fragments, this question takes him more and more time and distracts him from the fascinating process.

Leonid offers to divide the labor — he will cut glass, and you will calculate the area of the maximum fragment after each cut. Do you agree?

Input
The first line contains three integers w, h, n (2 ≤ w, h ≤ 200 000, 1 ≤ n ≤ 200 000).

Next n lines contain the descriptions of the cuts. Each description has the form H y or V x. In the first case Leonid makes the horizontal cut at the distance y millimeters (1 ≤ y ≤ h - 1) from the lower edge of the original sheet of glass. In the second case Leonid makes a vertical cut at distance x (1 ≤ x ≤ w - 1) millimeters from the left edge of the original sheet of glass. It is guaranteed that Leonid won't make two identical cuts.

Output
After each cut print on a single line the area of the maximum available glass fragment in mm2.

Examples
inputCopy
4 3 4
H 2
V 2
V 3
V 1
outputCopy
8
4
4
2
inputCopy
7 6 5
H 4
V 3
V 5
H 2
V 1
outputCopy
28
16
12
6
4
Note
Picture for the first sample test:

Picture for the second sample test:

题意:
给你一个矩阵,和q个询问,每个询问可以横着切或者竖着切,问你切之后剩下完整的的矩阵中面积最大的是多大?
思路:

线段树可以维护最长连续0.

我们可以按行和列建立2个线段树,

点的信息为0或者1,0代表没有被切,1代表已经被切。

,每一次查询行和列的最大连续0,行列加1后乘起来即是最大的矩阵面积。

为什么要加1?

我们01序列表示的是每一个点是否被切割,而矩阵转成点线的问题可以这样处理:

即有n行每一行m列小方块,那么转成点线(方便线段树处理)就建立为 1~n-1 行,1~m-1列

查询的时候+1 就是方格个数。

接下来我们看如何用线段树维护区间最长连续零的个数。

我们每一个区间维护这四个信息:

1、从左开始最长的连续零个数 (记为 Rnum)

2、从右开始最长连续零个数 ( 记为 Lnum)

3、区间最长连续零的个数、(记为num)

4、本区间是否全为0 (其实可以用3与区间的长度判断得出,但是多维护一个减少代码量。)

从儿子节点更新父节点:

1、从左开始最长连续零的个数:

如果左儿子全是0,则为左儿子的num+ 右儿子的Lnum

否则为 左儿子的Lnum

2、从右开始最长连续零的个数:

如果右儿子全是0,则为右儿子的num+ 左儿子的Rnum

否则为 右儿子的Rnum

3、区间最长连续零的个数:

max(左儿子的Lnum,右儿子的Rnum,左儿子的Rnum+右儿子的Lnum )

4、本区间是否全为0

最容易维护,判断左右儿子是否都全为0即可。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 200200;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node
{
    int l,r;
    int isall;
    int num;
    int lm;
    int rm;
};
node segment_tree1[maxn<<2];
node segment_tree2[maxn<<2];
void pushup(node * segment_tree,int rt)
{
    if(segment_tree[rt<<1].isall)
    {
        segment_tree[rt].isall=(segment_tree[rt<<1|1].isall);
        segment_tree[rt].num=segment_tree[rt<<1].lm+segment_tree[rt<<1|1].lm;
        segment_tree[rt].lm=segment_tree[rt<<1].lm+segment_tree[rt<<1|1].lm;
        if(segment_tree[rt<<1|1].isall)
        {
            segment_tree[rt].rm=segment_tree[rt<<1|1].num+segment_tree[rt<<1].rm;
        }else
        {
            segment_tree[rt].rm=segment_tree[rt<<1|1].rm;
        }
    }else if(segment_tree[rt<<1|1].isall)
    {
        segment_tree[rt].isall=(segment_tree[rt<<1].isall);
        segment_tree[rt].num=segment_tree[rt<<1|1].rm+segment_tree[rt<<1].rm;
        segment_tree[rt].rm=segment_tree[rt<<1|1].rm+segment_tree[rt<<1].rm;
        if(segment_tree[rt<<1].isall)
        {
            segment_tree[rt].lm=segment_tree[rt<<1|1].num+segment_tree[rt<<1].lm;
        }else
        {
            segment_tree[rt].lm=segment_tree[rt<<1].lm;
        }
    }else
    {
        segment_tree[rt].isall=0;
        segment_tree[rt].lm=segment_tree[rt<<1].lm;
        segment_tree[rt].rm=segment_tree[rt<<1|1].rm;
        segment_tree[rt].num=max(max(segment_tree[rt].lm,segment_tree[rt].rm),segment_tree[rt<<1].rm+segment_tree[rt<<1|1].lm);
        segment_tree[rt].num=max(segment_tree[rt].num,segment_tree[rt<<1].num);
        segment_tree[rt].num=max(segment_tree[rt].num,segment_tree[rt<<1|1].num);
    }

}
void build(node * segment_tree,int rt,int l,int r)
{
    segment_tree[rt].l=l;
    segment_tree[rt].r=r;
    if(l==r)
    {
        segment_tree[rt].isall=1;
        segment_tree[rt].lm=1;
        segment_tree[rt].rm=1;
        segment_tree[rt].num=1;
        return;
    }
    int mid=(l+r)>>1;
    build(segment_tree,rt<<1,l,mid);
    build(segment_tree,rt<<1|1,mid+1,r);
    pushup(segment_tree,rt);
}
int ask(node * segment_tree)
{
    return segment_tree[1].num;
}
void update(node * segment_tree,int rt,int x)
{
    if(segment_tree[rt].l==segment_tree[rt].r&&segment_tree[rt].l==x)
    {
        segment_tree[rt].isall=0;
        segment_tree[rt].lm=0;
        segment_tree[rt].rm=0;
        segment_tree[rt].num=0;
    }else
    {
        int mid=(segment_tree[rt].l+segment_tree[rt].r)>>1;
        if(x<=mid)
        {
            update(segment_tree,rt<<1,x);
        }else
        {
            update(segment_tree,rt<<1|1,x);
        }
        pushup(segment_tree,rt);
    }
}

int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int n,m;
    int q;
    scanf("%d %d %d",&n,&m,&q);
    build(segment_tree1,1,1,m-1);
    build(segment_tree2,1,1,n-1);
    while(q--)
    {
        char op;
        getchar();
        scanf("%c",&op);
        if(op=='H')
        {
            int x;
            scanf("%d",&x);
            update(segment_tree1,1,x);
        }else
        {
                int x;
            scanf("%d",&x);
            update(segment_tree2,1,x);
        }
        ll ans=(ask(segment_tree2)+1ll);
        ans*=(ask(segment_tree1)+1ll);
        printf("%lld\n",ans );
    }
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}




posted @ 2019-08-20 20:31  茄子Min  阅读(253)  评论(0编辑  收藏  举报