Codeforces 527C Glass Carving (最长连续0变形+线段树)
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
Input
Copy
4 3 4
H 2
V 2
V 3
V 1
Output
Copy
8
4
4
2
Input
Copy
7 6 5
H 4
V 3
V 5
H 2
V 1
Output
Copy
28
16
12
6
4
Note
Picture for the first sample test:
递归
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const int maxn = * 1e5 + ; struct SegTree {
ll ls, rs, max0;
bool is_all0;
}segTree[][maxn<<]; void pushup(int root, int flag) {
SegTree &cur = segTree[flag][root], &lc = segTree[flag][root<<], &rc = segTree[flag][root<<|];
cur.ls = lc.ls + (lc.is_all0 ? rc.ls : );
cur.rs = rc.rs + (rc.is_all0 ? lc.rs : );
cur.max0 = max(lc.rs + rc.ls, max(lc.max0, rc.max0));
cur.is_all0 = lc.is_all0 && rc.is_all0;
} void build(int L, int R, int root, int flag) {
if (L == R) {
segTree[flag][root].ls = segTree[flag][root].rs = segTree[flag][root].max0 = ;
segTree[flag][root].is_all0 = true;
return;
}
int mid = (L + R)>>;
build(L, mid, root<<, flag);
build(mid + , R, root<<|, flag);
pushup(root, flag);
} void update_node(int L, int R, int root, int pos, int flag) {
if (L == R) {
segTree[flag][root].ls = segTree[flag][root].rs = segTree[flag][root].max0 = ;
segTree[flag][root].is_all0 = false;
return;
}
int mid = (L + R)>>;
if (pos <= mid) {
update_node(L, mid, root<<, pos, flag);
}
else {
update_node(mid + , R, root<<|, pos, flag);
}
pushup(root, flag);
} ll query(int L, int R, int root, int qL, int qR, int flag) {
if (qL <= L && R <= qR) {
return segTree[flag][root].max0;
}
int mid = (L + R)>>;
ll temp = ;
if (qL <= mid) {
temp = max(temp, query(L, mid, root<<, qL, qR, flag));
}
if (qR > mid) {
temp = max(temp, query(mid + , R, root<<|, qL, qR, flag));
}
return temp;
} int main()
{
int W, H, q, x;
char c[];
while (scanf("%d %d %d", &W, &H, &q) == ) {
build(, W - , , );
build(, H - , , );
while (q--) {
scanf("%s %d", c, &x);
if (c[] == 'V') {
update_node(, W - , , x, );
}
else {
update_node(, H - , , x, );
}
printf("%I64d\n", (query(, W - , , , W - , ) + ) * (query(, H - , , , H - , ) + ));
}
}
}
非递归
#include <iostream>
#include <cstdio>
#include <cmath>
#define maxn 200001
using namespace std;
int L[maxn<<][];//从左开始连续零个数
int R[maxn<<][];//从右
int Max[maxn<<][];//区间最大连续零
bool Pure[maxn<<][];//是否全零
int M[];
void PushUp(int rt,int k){//更新rt节点的四个数据
Pure[rt][k]=Pure[rt<<][k]&&Pure[rt<<|][k];
Max[rt][k]=max(R[rt<<][k]+L[rt<<|][k],max(Max[rt<<][k],Max[rt<<|][k]));
L[rt][k]=Pure[rt<<][k]?L[rt<<][k]+L[rt<<|][k]:L[rt<<][k];
R[rt][k]=Pure[rt<<|][k]?R[rt<<|][k]+R[rt<<][k]:R[rt<<|][k];
}
void Build(int n,int k){//建树,赋初值
for(int i=;i<M[k];++i) L[M[k]+i][k]=R[M[k]+i][k]=Max[M[k]+i][k]=Pure[M[k]+i][k]=i<n;
for(int i=M[k]-;i>;--i) PushUp(i,k);
}
void Change(int X,int k){//切割,更新
int s=M[k]+X-;
Pure[s][k]=Max[s][k]=R[s][k]=L[s][k]=;
for(s>>=;s;s>>=) PushUp(s,k);
}
int main(void)
{
int w,h,n;
while(cin>>w>>h>>n){
//以下3行,找出非递归线段树的第一个数的位置。
M[]=M[]=;
while(M[]<h-) M[]<<=;
while(M[]<w-) M[]<<=;
//建树
Build(h-,);Build(w-,); for(int i=;i<n;++i){
//读取数据
char x;int v;
scanf(" %c%d",&x,&v);
//切割
x=='H'?Change(v,):Change(v,);
//输出
printf("%I64d\n",(long long)(Max[][]+)*(Max[][]+));
}
}
return ;
}
其他解法
https://blog.csdn.net/zearot/article/details/44759437
Codeforces 527C Glass Carving (最长连续0变形+线段树)的更多相关文章
- CodeForces 527C. Glass Carving (SBT,线段树,set,最长连续0)
原题地址:http://codeforces.com/problemset/problem/527/C Examples input H V V V output input H V V H V ou ...
- Codeforces 527C Glass Carving(Set)
意甲冠军 片w*h玻璃 其n斯普利特倍 各事业部为垂直或水平 每个分割窗格区域的最大输出 用两个set存储每次分割的位置 就能够比較方便的把每次分割产生和消失的长宽存下来 每次分割后剩下 ...
- Codeforces 527C Glass Carving
vjudge 上题目链接:Glass Carving 题目大意: 一块 w * h 的玻璃,对其进行 n 次切割,每次切割都是垂直或者水平的,输出每次切割后最大单块玻璃的面积: 用两个 set 存储每 ...
- CF 527C Glass Carving
数据结构维护二维平面 首先横着切与竖着切是完全没有关联的, 简单贪心,最大子矩阵的面积一定是最大长*最大宽 此处有三种做法 1.用set来维护,每次插入操作寻找这个点的前驱和后继,并维护一个计数数组, ...
- CF 150E Freezing with Style [长链剖分,线段树]
\(sol:\) 给一种大常数 \(n \log^2 n\) 的做法 考虑二分,由于是中位数,我们就二分这个中位数,\(x>=mid\)则设为 \(1\),否则为 \(-1\) 所以我们只需要找 ...
- 最大矩阵覆盖权值--(静态连续最大子段 (线段树) )-HDU(6638)Snowy Smile
这题是杭电多校2019第六场的题目 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638 题意:给你平面上n个点,每个点都有权值(有负权),让你计算一 ...
- Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树)
Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树) 题目链接 题意 给定一个nm的矩阵,每行取2k的矩阵,求总 ...
- Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)
题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...
- D. Babaei and Birthday Cake---cf629D(最长上升子序列和+线段树优化)
http://codeforces.com/problemset/problem/629/D 题目大意: 我第一反应就是求最长上升子序列和 但是数值太大了 不能直接dp求 可以用线段树优化一下 ...
随机推荐
- checked多选,取消,反选
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- javascript作用域原理
问题的提出 首先看一个例子: var name = 'laruence'; function echo() { alert(name); var name = 'eve'; alert(name); ...
- 2-4 zookeeper配置文件介绍,运行zk
心跳机制就是超过一定的时间之后,那么这个从节点就会被抛弃. zookeeper需要存储的数据,比如说事务文件等等,它都会存到这个dataDir目录下. 如果是伪分布式的集群环境,那么它的端口肯定是要变 ...
- springBoot 案例
一.工具 JDK1.7 Eclipse Maven 这里Eclipse集成Maven的这一步就省了! 二.编码 新建Maven Project 命名为:SpringBootDemo 选项如图 2.修改 ...
- 【摘自张宴的"实战:Nginx"】nginx模块开发
Nginx的模块不能够像Apache那样动态的加载,所以模块都要预先编译进Nginx的二进制可执行文件中. Nginx的模块有三种角色: 1. Handler(处理模块) 用于处理Http请求 ...
- redis 有用
浅谈redis (1)什么是redis? Redis 是一个基于内存的高性能key-value数据库. (有空再补充,有理解错误或不足欢迎指正) (2)Reids的特点 redis本质上是一 ...
- EZOJ #81
传送门 分析 每次拿a中最大的去匹配b中最小的 至于原因画个图感性思考一下就可以啦 代码 #include<iostream> #include<cstdio> #includ ...
- p2657 windy数
传送门 分析 首先这是一个询问一段区间内的个数的问题,所以我们可以用差分的思想用sum(R)-sum(L-1).然后我们考虑如何求出sum(n),我们用dp[i][j][k][t]表示考虑到第i位,最 ...
- java的泛型的技巧
最近学习scala,了解了两个概念:class和type,什么是class,就是具有相同的class对象,List<String> ,List<Integer>具有相同的cla ...
- C/C++中struct/union/class内存对齐
struct/union/class内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储 ...