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个 ...
随机推荐
- sql视频学习关键笔记(自用记单词与学习用)
sql字段类型 numeric(18,3)-18位整数加3位小数点(货币计量最好选这类型) sql关键字 insert. update. delete alter grant 授权. revoke 回 ...
- [洛谷P3243] 菜肴制作
问题描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1. 由于菜肴 ...
- facebook第三方登陆实践
未完,待续... 1.注册 到Facebook官网注册开发者账号,创建应用(开发者平台 https://developers.facebook.com),如果尚未注册账号的请注册账号并进行登录) 注册 ...
- SpringBoot搭建基于Spring+SpringMvc+Mybatis的REST服务
Maven Plugin管理 通常,让你的Maven POM文件继承 spring-boot-starter-parent,并声明一个或多个 Starter POMs依赖即可. spring-boot ...
- 嵌入式逻辑分析仪SignalTap II 设计范例
Crazy Bingo :嵌入式逻辑分析仪SignalTap II 设计范例 例程下载地址 http://www.cnblogs.com/crazybingo/archive/2011/07/26/ ...
- 【bzoj1176】[Balkan2007]Mokia
题目描述: 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. 输 ...
- 【CF10D】LCIS(LCIS)
题意:求两个序列的LCIS n,m<=300,a[i]<=1e9 题意:O(n^2) O(n^3)的话设dp[i,j]为A终点为a[1..i]且B终点为b[j]的最大长度,分a[i]==b ...
- HDU 4277 USACO ORZ(DFS暴搜+set去重)
原题代号:HDU 4277 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4277 原题描述: USACO ORZ Time Limit: 5000/1 ...
- pytho 解析fiddler 导出的har文件代码,自动录入api
参考:https://testerhome.com/topics/5276 har导出格式如下: { 'log': { 'pages': [], 'comment': 'exported @ 2019 ...
- Actor Roles 图示
Udemy上的教程<Unreal Multiplayer Mastery - Online Game Development in C++>中对Actor Roles的总结非常直观到位,一 ...