首页 > 其他分享 >172 树套树 线段树套平衡树

172 树套树 线段树套平衡树

时间:2022-08-17 14:24:53浏览次数:101  
标签:树套 int res 线段 tr query 172 define

视频链接:

Luogu P3380 【模板】二逼平衡树(树套树)

// 需要开O2
#include <iostream> #include <algorithm> using namespace std; #define N 2000010 #define INF 2147483647 #define ls(x) tr[x].s[0] #define rs(x) tr[x].s[1] #define lc u<<1 #define rc u<<1|1 struct node{ int s[2],p,v; int size; void init(int v1,int p1){ v=v1,p=p1; size=1; } }tr[N];//splay int L[N],R[N],T[N];//线段树 int n,m,w[N],idx; //////////splay void pushup(int x){ tr[x].size=tr[ls(x)].size+tr[rs(x)].size+1; } void rotate(int x){ int y=tr[x].p,z=tr[y].p; int k=tr[y].s[1]==x; tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z; tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y; tr[x].s[k^1]=y,tr[y].p=x; pushup(y),pushup(x); } void splay(int &root,int x,int k){ while(tr[x].p != k){ int y=tr[x].p,z=tr[y].p; if(z != k) if((rs(y)==x)^(rs(z)==y)) rotate(x); else rotate(y); rotate(x); } if(!k) root=x; } void insert(int &root,int v){ int u=root,p=0; while(u) p=u,u=tr[u].s[v>tr[u].v]; u=++ idx; if(p) tr[p].s[v>tr[p].v]=u; tr[u].init(v,p); splay(root,u,0); } int get_k(int root,int v){ int u=root,res=0; while(u){ if(tr[u].v<v) res+=tr[ls(u)].size+1,u=rs(u); else u=ls(u); } return res; } void update(int &root,int x,int y){ int u=root; while(u){ if(tr[u].v==x) break; if(tr[u].v<x) u=rs(u); else u=ls(u); } splay(root,u,0); int l=ls(u),r=rs(u); while(rs(l)) l=rs(l); while(ls(r)) r=ls(r); splay(root,l,0),splay(root,r,l); ls(r)=0; pushup(r),pushup(l); insert(root,y); } int get_pre(int root,int v){ int u=root,res=-INF; while(u){ if(tr[u].v<v) res=max(res,tr[u].v),u=rs(u); else u=ls(u); } return res; } int get_nxt(int root,int v){ int u=root,res=INF; while(u){ if(tr[u].v>v) res=min(res,tr[u].v),u=ls(u); else u=rs(u); } return res; } //////////线段树 void build(int u,int l,int r){ L[u]=l,R[u]=r; insert(T[u],-INF),insert(T[u],INF); for(int i=l; i<=r; i++) insert(T[u],w[i]); if(l==r) return; int mid=l+r>>1; build(lc,l,mid); build(rc,mid+1,r); } void change(int u,int p,int x){ update(T[u],w[p],x); if(L[u]==R[u]) return; int mid=L[u]+R[u]>>1; if(p<=mid) change(lc,p,x); else change(rc,p,x); } int query_rank(int u,int a,int b,int x){ if(L[u] >= a && R[u]<=b) return get_k(T[u],x)-1; int mid=L[u]+R[u]>>1,res=0; if(a<=mid) res += query_rank(lc,a,b,x); if(b>mid) res += query_rank(rc,a,b,x); return res; } int query_pre(int u,int a,int b,int x){ if(L[u] >= a && R[u]<=b) return get_pre(T[u],x); int mid=L[u]+R[u]>>1,res=-INF; if(a<=mid) res=max(res,query_pre(lc,a,b,x)); if(b>mid) res=max(res,query_pre(rc,a,b,x)); return res; } int query_nxt(int u,int a,int b,int x){ if(L[u] >= a && R[u]<=b) return get_nxt(T[u],x); int mid=L[u]+R[u]>>1,res=INF; if(a<=mid) res=min(res,query_nxt(lc,a,b,x)); if(b>mid) res=min(res,query_nxt(rc,a,b,x)); return res; } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&w[i]); build(1,1,n); while(m -- ){ int op,a,b,x; scanf("%d",&op); if(op==1){ scanf("%d%d%d",&a,&b,&x); printf("%d\n",query_rank(1,a,b,x)+1); } else if(op==2){ //logn*logn*logn scanf("%d%d%d",&a,&b,&x); int l=0,r=1e8; while(l<r){ int mid=l+r+1>>1; if(query_rank(1,a,b,mid)+1<=x) l=mid; else r=mid-1; } printf("%d\n",r); } else if(op==3){ scanf("%d%d",&a,&x); change(1,a,x); w[a]=x; } else if(op==4){ scanf("%d%d%d",&a,&b,&x); printf("%d\n",query_pre(1,a,b,x)); } else{ scanf("%d%d%d",&a,&b,&x); printf("%d\n",query_nxt(1,a,b,x)); } } return 0; }

 

标签:树套,int,res,线段,tr,query,172,define
From: https://www.cnblogs.com/dx123/p/16595024.html

相关文章

  • 线段树模板【带懒标记】
    #include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintN=1e5+10;inta[N];structnode{  intl,r;  lladd,sum;  node(){  ......
  • YbtOJ 「数据结构」第4章 线段树
    不想dp了怎么办?开个新坑吧。例题1.求区间和树状数组不香吗,28行解决(bushi所以懒得打线段树了。code#include<bits/stdc++.h>#defineintlonglongusingnamespac......
  • 洛谷 P6242 【模板】线段树 3 吉司机线段树 区间取最小值 维护历史最大值和区间和
    题目背景本题是线段树维护区间最值操作与区间历史最值的模板。题目描述给出一个长度为 nn 的数列 AA,同时定义一个辅助数组 BB,BB 开始与 AA 完全相同。接下来......
  • 线段树----区间问题的神
    《标准线段树》  普通的线段树,其区间一般都是一个序列的数的个数,但还是要根据不同题目来判断注意:tr[]空间是N*4,N为最大范围《单点修改,区间查询》原题:https://www.......
  • 动态开点线段树
    动态开点线段树为了准备google的面试刷题的时候发现这个知识点其实我一直不太熟悉,所以专门写一篇blog准备一下。我们将从以下几个方面去讲解:目录动态开点线段树什么是......
  • 线段树
    线段树学习笔记1.线段树简介线段树,是一种二叉搜索树,其每一个节点表示了一段区间。线段树支持的操作有:区间求和或最大/最小值,时间复杂度\(O(logN)\)(p.s.后面代......
  • luoguP3521 [POI2011]ROT-Tree Rotations【线段树】
    你要写热,就不能只写热。要写酷暑,写骄阳,写他人耳闻便生恐的炙烤和炎灼。要写白日出门一刻便肤色黝黑,背心透彻。写求雨心切,写出行伞遮。写夜晚不停的风扇和蝉聒。写鸡......
  • luoguP3224 [HNOI2012]永无乡【线段树,并查集】
    洞庭青草,近中秋,更无一点风色。玉鉴琼田三万顷,着我扁舟一叶。素月分辉,明河共影,表里俱澄澈。悠然心会,妙处难与君说。应念岭表经年,孤光自照,肝胆皆冰雪。短发萧骚襟袖冷,稳泛......
  • 【学习笔记】线段树优化建图
    先开坑,有时间再说。例题CF786BLegacyCode//线段树优化建图,从寒假一直咕到暑假//之前觉得难得不行,现在看还是挺好理解的#include<queue>#include<cstdio>#includ......
  • P6144 [USACO20FEB]Help Yourself P(DP+线段树)
    P6144[USACO20FEB]HelpYourselfP将线段按照了\(r\)排序,设右端点为\(r\)的答案为\(f_r\),发现这样转移非常困难。\(\color{yellow}{\bigstar\texttt{Trick}}\):区间......