吉司机线段树思路整理[bzoj4355 Play with sequence]

原题目链接
原代码来自attack

#include<cstdio>
#include<algorithm>
#define LL long long
//#define int long long
using namespace std;
const int MAXN = 3 * 1e5 + 10;
const LL INF = 1e10 +10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
#define ls k << 1
#define rs k << 1 | 1
int N, Q;
int a[MAXN];
struct Node {
    int l, r, siz有多宽, cnt有几个最小值;
    LL Mx最小值标记, add加法标记, mn最小值, se次小值, cov刷值标记;
}T[MAXN << 2];
void update(int k) {
    更新mn, se, cnt
}
void MemP(int k, LL val) {
    打刷值标记 cnt变成size 最小值变成val
}
void AddP(int k, LL val) {
    如果有次大值,最小值标记 add它
    最小值标记和加法标记是肯定要更新的
}
void MaxP(int k, LL val) {
    刷新mn, mx
}
void pushdown(int k) {
    如果有刷值标记 下放mem
    如果有add标记 下放add
    如果有最小值更新标记 下放max操作
    记得清空标记
}
void Build(int k, int ll, int rr) {
    初始化
    if(ll == rr) 最小值是自己,有一个
    下推,update
}
void IntMem(int k, int ll, int rr, LL val) {//下放刷值操作
    if(位于目标区间) 执行mem操作
    pushdown,下推,update
}
void IntAdd(int k, int ll, int rr, LL val) {//下放add操作
    if(位于目标区间) 执行add操作
    pushdown,下推,update
}
void IntMax(int k, int ll, int rr, LL val) {//下放取max操作
    if(val比最小值小) return ;
    if(位于目标区间并且val在(最小值,次小值)时,只对最小值有影响) 执行max操作;
   pushdown,下推,update
}
LL Query() {
    if(ll <= T[k].l && T[k].r <= rr) 如果最小数是0 返回有几个 不然就是没有啦
    pushdown并下推
}
main() {
    N = read(); Q = read();
    for(int i = 1; i <= N; i++) a[i] = read();
    Build(建树); 树中不会有小于0的数哦
    while(Q--) {
        int opt = read(), l = read(), r = read(), val;
        if(opt == 3) printf("%d\n", Query(询问区间中值为0的个数));
        else {
            val = read();
            if(opt == 1) IntMem(给区间每个数赋值);
            else {
                IntAdd(给区间每个数加x);
                IntMax(判断区间每个数和0的大小,并更新);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hjmmm/p/10960754.html

时间: 2024-10-28 19:55:23

吉司机线段树思路整理[bzoj4355 Play with sequence]的相关文章

bzoj4355 Play with sequence(吉司机线段树)题解

题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 赋值为\(x\) \(2.\)区间\([L,R]\) 赋值为\(max(a[i] + x, 0)\) \(3.\)区间\([L,R]\) 询问\(0\)个数 已知初始值\(\geq 0\),\(x\geq0\). 思路: 吉司机线段树. 操作\(1\)可以直接打覆盖标记. 操作\(2\)可以分为两步:区间加\(x\),然后取区间\(max(a[i],0)\). 操作\(3\)只要维护最小值的个数,因为不管怎么操作最

【模板】吉司机线段树 HDU 5306 Gorgeous Sequence

也叫小清新线段树,用于解决区间最值修改问题 具体可以参考jiry_2神犇的集训队论文和WC2016上的PPT 此题就作为模板好了,模板的话写法是比较精妙的 #include<bits/stdc++.h> using namespace std; #define go(i,a,b) for(int i=a;i<=b;++i) #define com(i,a,b) for(int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a))

HDU 5306 吉司机线段树

思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; const int N=1000050; int cases,n,m,op,xx,yy,zz; typedef long long ll; struct SegTree{int max1,max2,maxnum,lazy;ll s

hdu6521 吉司机线段树

http://acm.hdu.edu.cn/showproblem.php?pid=6521 待填 代码 #include<bits/stdc++.h> #define ls o<<1 #define rs o<<1|1 #define ll long long using namespace std; const int MAXN = 5e5+5; int Mx[MAXN<<2],Mx2[MAXN<<2],Mn[MAXN<<2],l

HDU4695 最假女选手(吉司机线段树)

本题原理和代码讲解会在近日放到b站,对题目解法不是很了解的同学可以关注b站 朝暮不思 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<cstring> #include<map> #include<set> using

bzoj 2957 楼房重建 (线段树+思路)

链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2957 思路: 用分块可以很简单的过掉,但是这道题也可以用线段树写. 分类讨论左区间最大值对右区间取值的影响,这样每次都只计算左右区间其中一个,复杂度就降成了logn. 实现代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define r

线段树入门整理、

线段树(interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式. [声明] 1 #include<cstdio> 2 #include<cmath> 3 const int MAXNODE = 2097152; 4 const int MAX = 1000003; 5 struct NODE{ 6 int left,right; // 区间[left,right] . 7 int value; // 节点区间对应的权值.

线段树模板整理

一.点修改: 二.区间修改: (1)区间中每点值直接修改为v. sum = 0; ma = 0; mi = INT_INF; query(x, y, 1, 1, N); 代码如下: int sumv[MAXN << 2], maxv[MAXN << 2], minv[MAXN << 2], setv[MAXN << 2]; int sum, ma, mi; void maintain(int id, int L, int R){ int lc = id &l

COGS 2638. 数列操作ψ 线段树

传送门 : COGS 2638. 数列操作ψ 线段树 这道题让我们维护区间最大值,以及维护区间and,or一个数 我们考虑用线段树进行维护,这时候我们就要用到吉司机线段树啦 QAQ 由于发现若干次and,or之后,如果数据分布均匀,那么几乎所有的数在若干次操作后都会变成同一个数 因为我们的and操作中的0位,以及or操作当中的1位,都是可以把整个区间的那一二进制位重置为相同的 我们考虑利用这一个性质 如果我们直接维护一个区间内的值是否是相同的,那么效果会差很多. 我们发现我们在进行and操作的时