Codeforces - 1199D - Welfare State - 单调栈 / 线段树
https://codeforc.es/contest/1199/problem/D
其实后来想了一下貌似是个线段树的傻逼题。
单调栈是这样思考的,每次单点修改打上一个最终修改的时间戳。每次全体修改就push进去单调栈。首先比新的全体修改的x小的(等的也)全部出栈,这样子单调栈里面就是一个递减的序列,而时间戳是递增的。
最后对于每一个有修改标记的,在时间戳上面二分找到他的下一次修改,那么这个修改绝对就是足够大的。假如没有查找成功,则说明不存在最后一次修改。(可以通过在最后入栈一个0操作来统一),没有修改标记的那就直接赋值最大的全体修改。(相当于对0进行查询)
其实也是nlogn的。常数估计更小。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int x = 0;
char c = getchar();
for(; c < '0' || c > '9'; c = getchar());
for(; c >= '0' && c <= '9'; c = getchar())
x = (x << 3) + (x << 1) + c - '0';
return x;
}
inline void _write(int x) {
if(x > 9)
_write(x / 10);
putchar(x % 10 + '0');
}
inline void write(int x) {
if(x < 0) {
putchar('-');
x = -x;
}
_write(x);
putchar('\n');
}
const int MAXN=200005;
int n, q;
int a[MAXN],lc[MAXN];
int st1[MAXN],st2[MAXN],stop;
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
n = read();
for(int i = 1; i <= n; ++i)
a[i] = read();
q = read();
for(int qi = 1; qi <= q; qi++) {
int op = read(), p, x;
if(op == 1) {
p = read(), x = read();
a[p] = x;
lc[p] = qi;
} else {
x = read();
while(stop && st1[stop] <= x)
--stop;
st1[++stop] = x;
st2[stop] = qi;
}
}
st1[++stop] = 0;
st2[stop] = q + 1;
for(int i = 1; i <= n; ++i)
a[i] = max(a[i], st1[lower_bound(st2 + 1, st2 + 1 + stop, lc[i]) - st2]);
for(int i = 1; i <= n; ++i)
printf("%d%c", a[i], " \n"[i == n]);
}
其实当时也在想,每次lazy更新2操作不就可以了吗?这样就直接是线段树。每次对点更新把一路上的lazy标记push下去,然后到叶子的时候把这个失效的lazy给清空了。query的时候记得要max上lazy,因为有一些叶子并没有被1操作对点更新但是lazy也确实传到这个叶子了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXM = 200000;
int a[MAXM + 5];
int lazy[(MAXM << 2) + 5];
inline void push_down(int o, int l, int r) {
if(lazy[o]) {
lazy[o << 1] = max(lazy[o << 1], lazy[o]);
lazy[o << 1 | 1] = max(lazy[o << 1 | 1], lazy[o]);
lazy[o] = 0;
}
}
void update1(int o, int l, int r, int x, int v) {
if(x <= l && r <= x) {
lazy[o]=0;
a[x] = v;
return;
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(x <= m)
update1(o << 1, l, m, x, v);
if(x >= m + 1)
update1(o << 1 | 1, m + 1, r, x, v);
}
}
void update2(int o, int l, int r, int v) {
lazy[o] = max(lazy[o], v);
return;
}
int query(int o, int l, int r, int x) {
if(x <= l && r <= x) {
return max(a[x], lazy[o]);
} else {
push_down(o, l, r);
int m = (l + r) >> 1;
if(x <= m)
return query(o << 1, l, m, x);
if(x >= m + 1)
return query(o << 1 | 1, m + 1, r, x);
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
int q;
scanf("%d", &q);
for(int i = 1; i <= q; ++i) {
int op;
scanf("%d", &op);
if(op == 1) {
int x, v;
scanf("%d%d", &x, &v);
update1(1, 1, n, x, v);
} else {
int x;
scanf("%d", &x);
update2(1, 1, n, x);
}
}
for(int i = 1; i <= n; ++i) {
a[i] = query(1, 1, n, i);
printf("%d%c", a[i], " \n"[i == n]);
}
}
Codeforces - 1199D - Welfare State - 单调栈 / 线段树的更多相关文章
- [Codeforces 1199D]Welfare State(线段树)
[Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...
- The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)
题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...
- 2019南昌网络赛-I(单调栈+线段树)
题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...
- 网络赛 I题 Max answer 单调栈+线段树
题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...
- 南昌邀请赛I.Max answer 单调栈+线段树
题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ...
- [CF1083D]The Fair Nut’s getting crazy[单调栈+线段树]
题意 给定一个长度为 \(n\) 的序列 \(\{a_i\}\).你需要从该序列中选出两个非空的子段,这两个子段满足 两个子段非包含关系. 两个子段存在交. 位于两个子段交中的元素在每个子段中只能出现 ...
- 【CF671E】Organizing a Race 单调栈+线段树
[CF671E]Organizing a Race 题意:n个城市排成一排,每个城市内都有一个加油站,赛车每次经过第i个城市时都会获得$g_i$升油.相邻两个城市之间由道路连接,第i个城市和第i+1个 ...
随机推荐
- Bloom Filter的算法
Bloom Filter的算法: 为了降低冲突的概念,Bloom Filter使用了多个哈希函数,而不是一个.创建一个m位BitSet,先将所有位初始化为0,然后选择k个不同的哈希函数.第i个哈希函 ...
- 2019年8月5日~8月11日 第六周JAVA学习总结
本周主要进行了对JAVA基础的学习和PTA代码的编写,平均每天花在学习上的时间约3个小时,花在代码上的时间约2个小时,花在解决问题上的时间约1.5个小时. 下周打算继续JAVA的学习,完成java面向 ...
- 【leetcode】Reaching Points
题目如下: A move consists of taking a point (x, y) and transforming it to either (x, x+y) or (x+y, y). G ...
- es6 语法使用
一.相关背景介绍 我们现在大多数人用的语法javascript 其实版本是ecmscript5,也是就es5.这个版本己经很多年了,且完美被各大浏览器所支持.所以很多学js的朋友可以一直分不清楚es5 ...
- Sql server时间转时间long
DATEDIFF( S, '1970-01-01 00:00:00', a.endor_date ) - 8 * 60*60 ) actionTime, SELECT DATEADD(S,116070 ...
- MCU2FPGA之SPI时序总线
转载自:http://blog.csdn.net/ce123/article/details/6895408 SPI总线有四种工作方式(SP0, SP1, SP2, SP3),其中使用的最为广泛的是S ...
- 6.12友谊赛T4城市交通费题解
与普通的最短路径不同的是,题目中新引入了一个计入总体的费用——城市建设费.由于城市建设费由整体的某最大值决定,导致解没有最优子结构的性质,给思维带来难度. 既然最棘手的是城市建设费,我们就对它分类讨论 ...
- APIO2019解题报告
「APIO 2019」奇怪装置 题目描述 有无限个二元组,每个二元组为\(((t+\left\lfloor\frac{t}{B} \right\rfloor)\%A,t \% B)\),给出一些区间, ...
- 4.16中Montage的一些变化
用4.16版本跟着网上的几篇Montage教程(分别是对应4.6和4.8版本)做,遇到各种各样的问题,经过各种搜索和分析,最终终于搞定了. 4.16版的Montage和之前有了不小的变化,总结如下: ...
- uniapp开发
问题1:去掉导航条 给一个单独的页面隐藏顶部的 导航栏 可以在pages.json里 单独的路由style下面配置 "app-plus": {"titleNView&q ...