日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【模板】吉老师线段树

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【模板】吉老师线段树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ACM模板


目錄

      • 區間取最值

區間取最值

Gorgeous Sequence

區間最值操作往往采用以下辦法

線段樹維護:

  • 區間最大值mx\text{mx}mx
  • 區間嚴格次大值smx\text {smx}smx
  • 區間和sum\text{sum}sum
  • 區間最大值個數cnt\text{cnt}cnt
  • 區間最值懶標記lazy\text{lazy}lazy

實現區間最小值操作,考慮u節點維護的區間,進行如下處理

  • mx≤x\text{mx}\leq xmxx,顯然這次修改不會對這個節點維護的區間產生影響,直接退出。
  • smx<x<mx\text{smx}<x<\text{mx}smx<x<mx,顯然這次修改只會影響到這個區間所有的最大值,由此直接根據最大值個數更新區間和并且更新區間最大值并打上懶標記然后退出即可。
  • x≤smx\text{x}\leq \text{smx}xsmx,無法直接更新于是遞歸左右子樹。

時間復雜度請直接查閱吉老師2016年國家集訓隊論文(不太會~

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<stack> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int mod=998244353; const int N=1000010; // 快讀 template <class T> inline void read(T &res) {res = 0; bool bo = 0; char c;while (((c = getchar()) < '0' || c > '9') && c != '-');if (c == '-') bo = 1; else res = c - 48;while ((c = getchar()) >= '0' && c <= '9')res = (res << 3) + (res << 1) + (c - 48);if (bo) res = ~res + 1; } struct node {int l,r;ll mx,smx,sum;int cnt;ll lazy; }tree[N<<2]; int n,m; ll a[N]; void pushup(int u) {tree[u].sum=tree[u<<1].sum+tree[u<<1|1].sum;if(tree[u<<1].mx>tree[u<<1|1].mx){tree[u].mx=tree[u<<1].mx;tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].mx);tree[u].cnt=tree[u<<1].cnt;}else if(tree[u<<1].mx<tree[u<<1|1].mx){tree[u].mx=tree[u<<1|1].mx;tree[u].smx=max(tree[u<<1|1].smx,tree[u<<1].mx);tree[u].cnt=tree[u<<1|1].cnt;}else {tree[u].mx=tree[u<<1|1].mx;tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].smx);tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;} } void pushlazy(int u,ll x) {if(tree[u].mx<=x) return; tree[u].sum+=(x-tree[u].mx)*tree[u].cnt;tree[u].mx=tree[u].lazy=x; } void pushdown(int u) {if(tree[u].lazy==-1) return;pushlazy(u<<1,tree[u].lazy),pushlazy(u<<1|1,tree[u].lazy);tree[u].lazy=-1; } void build(int u,int l,int r) {tree[u]={l,r,0,-1,0,0,-1};if(l==r) {tree[u].mx=tree[u].sum=a[l];tree[u].cnt=1;return;}int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u); } void modify(int u,int l,int r,ll x) {if(x>=tree[u].mx) return;if(tree[u].l>=l&&tree[u].r<=r&&tree[u].smx<x){pushlazy(u,x);return;}pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(l<=mid) modify(u<<1,l,r,x);if(r>mid) modify(u<<1|1,l,r,x);pushup(u);} ll qmax(int u,int l,int r) {if(tree[u].l>=l&&tree[u].r<=r) return tree[u].mx;int mid=tree[u].r+tree[u].l>>1;pushdown(u);ll v=-1;if(l<=mid) v=max(v,qmax(u<<1,l,r));if(r>mid) v=max(v,qmax(u<<1|1,l,r));pushup(u);return v; } ll qsum(int u,int l,int r) {if(tree[u].l>=l&&tree[u].r<=r) return tree[u].sum;int mid=tree[u].r+tree[u].l>>1;pushdown(u);ll v=0;if(l<=mid) v+=qsum(u<<1,l,r);if(r>mid) v+=qsum(u<<1|1,l,r);pushup(u);return v; } int main() {//IO;int T=1;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%lld",&a[i]);build(1,1,n);while(m--){int op,l,r;scanf("%d%d%d",&op,&l,&r);if(op==0){ll v;scanf("%lld",&v);modify(1,l,r,v);}else if(op==1)printf("%lld\n",qmax(1,l,r));elseprintf("%lld\n",qsum(1,l,r));}}return 0; }

總結

以上是生活随笔為你收集整理的【模板】吉老师线段树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。