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. display:line-block

    1.那是因为第二个标签是inline-block,它的对齐方式是基线对齐,对齐的是第一个元素里面字的下划线,所以第二个元素的下边缘对齐的是1的下划线,只要在第二个元素里面加内容或者加个空格( )就可以 ...

  2. spring IOC(Spring 生命周期,先1.构造方式,2,初始化方法,3,目标方法,4,销毁方法)

  3. 洛谷P4391 [BOI2009]Radio Transmission 无线传输——题解

    题目传送 假如我们有一个用于循环连接的最短串ans,考虑用它造出来的数据(即输入的字符串s)有什么特点.发现:ans自我连接出一个大串z后从中取出的一个子串即为s,对s造一个KMP算法中的next数组 ...

  4. TCP学习笔记

    TCP/IP 协议分层模型 TCP/IP 协议族按层次分别分为以下 4 层:应用层.传输层.网络层和数据链路层.层次化之后,每个层级只需要考虑自己的任务就可以了,不再需要弄清其他层级的功能了. TCP ...

  5. Qt中图元对象的多重集成

    在继承自定义QGraphicsItem图元对象时,有时需要用到信号/槽机制,由于QGraphicsItem非QObject的子类 所以需要多重继承QObject,有一点需要特别注意:就是继承的顺序,一 ...

  6. POJ 1384 Piggy-Bank (完全背包)

    Piggy-Bank 题目链接: http://acm.hust.edu.cn/vjudge/contest/130510#problem/F Description Before ACM can d ...

  7. [CSP-S模拟测试]:visit(组合数学+exLucas+CRT)

    题目传送门(内部题6) 输入格式 第一行包含两个整数$T$,$MOD$:第二行包含两个整数$n$,$m$,表示$dirty$房子的位置. 输出格式 一行一个整数,表示对$MOD$取模之后的答案. 样例 ...

  8. 《SQL Server 2012 T-SQL基础》读书笔记 - 3.联接查询

    Chapter 3 Joins Cross Joins(交叉联接)就是返回两个表的笛卡尔积(m行的表cross join一个n行的表得到一个m * n行的结果),它有两种标准SQL语法,第一种: SE ...

  9. 双边滤波Matlab代码

    %简单地说: %A为给定图像,归一化到[,]的矩阵 %W为双边滤波器(核)的边长/ %定义域方差σd记为SIGMA(),值域方差σr记为SIGMA() %%%%%%%%%%%%%%%%%%%%%%%% ...

  10. Qualcomm 8X camera过程解析【转】

    本文转载自:http://blog.csdn.net/gabbzang/article/details/19906687 http://www.01yun.com/mobile_development ...