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 - 单调栈 / 线段树的更多相关文章

  1. [Codeforces 1199D]Welfare State(线段树)

    [Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...

  2. 洛谷P4198 楼房重建 单调栈+线段树

    正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...

  3. 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)

    2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...

  4. The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...

  5. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  6. 网络赛 I题 Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...

  7. 南昌邀请赛I.Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 Alice has a magic array. She suggests that the value of a in ...

  8. [CF1083D]The Fair Nut’s getting crazy[单调栈+线段树]

    题意 给定一个长度为 \(n\) 的序列 \(\{a_i\}\).你需要从该序列中选出两个非空的子段,这两个子段满足 两个子段非包含关系. 两个子段存在交. 位于两个子段交中的元素在每个子段中只能出现 ...

  9. 【CF671E】Organizing a Race 单调栈+线段树

    [CF671E]Organizing a Race 题意:n个城市排成一排,每个城市内都有一个加油站,赛车每次经过第i个城市时都会获得$g_i$升油.相邻两个城市之间由道路连接,第i个城市和第i+1个 ...

随机推荐

  1. Ubuntu 压缩文件命令

    tar -czvf name-of-archive.tar.gz /path/to/directory-or-file -c: Create an archive. -z: Compress the ...

  2. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  3. C文件 CMakeList.txt编译器配置错误的问题 error:invalid conversion from 'int' to 'LAYER_TYPE' [-fpermissive]....

    在编译C工程时,遇到了如下错误: 一般看到类型错误,主要考虑是不是编译器错了. 以下引用:https://www.cnblogs.com/liushui-sky/p/7729838.html 后缀为. ...

  4. android 7.0适配(总结)

    file_paths.xml <?xml version="1.0" encoding="utf-8"?><paths xmlns:andro ...

  5. mysql CHECK约束 语法

    mysql CHECK约束 语法 作用:CHECK 约束用于限制列中的值的范围. 直线电机 说明:如果对单个列定义 CHECK 约束,那么该列只允许特定的值.如果对一个表定义 CHECK 约束,那么此 ...

  6. Java——抽象类

    [抽象类] 抽象类中方法有定义的必要,但是没有实现的必要,因为需要子类进行重写.

  7. 开始玩矩阵了!先来一道入门题![SDOI2008]递归数列

    [SDOI2008]递归数列 题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + c ...

  8. Packet Transactions: High-level Programming for Line-Rate Switches

    Name of article:Packet Transactions: High-level Programming for Line-Rate Switches Origin of the art ...

  9. Linux内核调试方法总结之dumpsys

    dumpsys [用途]Android系统提供的dumpsys工具可以用来查看系统服务信息与状态. [使用说明] adb shell dumpsys <service> [<opti ...

  10. 线段树板子1(洛谷P3372)

    传送 一道线段树板子(最简单的) 似乎之前在培训里写过线段树的样子?不记得了 何为线段树? 一般就是长成这样的树,树上的每个节点代表一个区间.线段树一般用于区间修改,区间查询的问题. 我们如何种写一棵 ...