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求 可以用线段树优化一下 ...
随机推荐
- 如何使CPU占用率为50%
在Linux下,CPU的状态分为系统态,用户态和空闲态,分别指系统内核执行时间,处于用户态的时间和空闲系统进程执行的时间.三者之和就是CPU的总时间. CPU的利用率就是非空闲进程占用时间的比例. 1 ...
- ROS Learning-016 Arduino-For-ROS-001 搭建 Arduino 和 ROS 之间相连接的开发环境
Arduino For ROS-001 - 搭建 ROS 和 Arduino 相连接的开发环境 我的Ubuntu系统:Ubuntu 14.04.10 TLS 32位 Arduino的版本:Arduin ...
- Java-马士兵设计模式学习笔记-工厂模式-单例及多例
一.单例的作用是用于控制类的生成方式,而不让外部类任意new对象 1.Car.java import java.util.ArrayList; import java.util.List; publi ...
- 数字图像处理实验(7):PROJECT 04-03 , Lowpass Filtering 标签: 图像处理MATLAB 2017-05-25 09:30 109人
实验要求: Objective: To observe how the lowpass filtering smoothes an image. Main requirements: Ability ...
- p1129 [ZJOI2007]矩阵游戏
传送门 分析 不难想到将黑点的行列连边,然后判断最大匹配是否等于n 代码 #include<iostream> #include<cstdio> #include<cst ...
- 100078D Domestic Networks
传送门 题目大意 有两种染料,给定它们的单价和数量,每染色一米需耗费一个单位的染料,一条边只能用一种燃料,给你一张图,要求你将其中的一些边染色使得在满足图联通的情况下花费最小并输出方案. 分析 首先, ...
- Luogu 4139 上帝与集合的正确用法
扩展欧拉定理:$a^{b} \equiv a^{b Mod \varphi (p) + \varphi (p)} (Mod p) $ $(b \geq \varphi (p))$ . 这道题 ...
- 12. git常用语法总结
git介绍与安装这里不再多说,再说也不如廖雪峰大佬总结的优秀: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67 ...
- epoll聊天室的实现
1.服务端 a. 支持多个用户接入,实现聊天室的基本功能 b. 使用epoll机制实现并发,增加效率 2. 客户端 a. 支持用户输入聊天消息 b. 显示其他用户输入的信息 c. 使用fork创建两个 ...
- Mysql 大数据量导入程序
Mysql 大数据量导入程序<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...