线段树动态开点 - - - > 线段树合并
生活随笔
收集整理的這篇文章主要介紹了
线段树动态开点 - - - > 线段树合并
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
逆序對
代碼
P3224 [HNOI2012]永無鄉 并查集+線段樹合并? ? ? ?????
代碼
P5494 【模板】線段樹分裂
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<set> using namespace std;typedef long long LL; typedef pair<int,int> PII;const int N=3e5+10; int rt[N],ls[N<<4],rs[N<<4],idx,id; // rt 是具體某些樹的根節點,還有其他的不需要記錄在內,比如分裂的時候的tmp; LL val[N<<4]; // 空間管理; int rub[N<<4],cnt; void del(int &u){rub[cnt++]=u;val[u]=0;u=ls[u]=rs[u]=0;return;} void newnode(int &u){u=cnt?rub[--cnt]:++idx;} // end // 單點修改 void modify(int &u,int l,int r,int num,int time) {if(!u)newnode(u);val[u]+=time;if(l==r)return ; // 結束條件 int mid=l+r>>1;if(num<=mid)modify(ls[u],l,mid,num,time);else modify(rs[u],mid+1,r,num,time); } // 查詢第 x 大的元素 查詢的時候不會遍歷到空節點; int quary(int u,int l,int r,LL x) {if(l==r)return l;// 結束條件 int mid=l+r>>1;LL t=val[ls[u]];return x>t? quary(rs[u],mid+1,r,x-t):quary(ls[u],l,mid,x); } // 區間和 LL quary(int u,int l,int r,int L,int R) {if(!u)return 0; // 空節點不訪問 if(L<=l&&R>=r)return val[u];int mid=l+r>>1;LL sum=0;if(L<=mid) sum=quary(ls[u],l,mid,L,R);if(R>mid)sum+=quary(rs[u],mid+1,r,L,R);return sum; } // 合并 void merge(int &a,int &b) {if(!a||!b){a+=b;return ;}val[a]+=val[b];merge(ls[a],ls[b]);merge(rs[a],rs[b]);del(b); } // 分裂 a中保留前 x 個元素 其余給 b; void split(int &a,int &b,LL x) {if(!a)return ;newnode(b);LL t=val[ls[a]];if(x>t)split(rs[a],rs[b],x-t); // 那就把a的右半部分分割給 b else swap(rs[b],rs[a]); // 否則右半部分直接給 b if(x<t)split(ls[a],ls[b],x); // 需要分科左半部分 val[b]=val[a]-x; // 計算剩余元素 val[a]=x;return ; }int main() {int n,m;scanf("%d%d",&n,&m);for(int i=1,x;i<=n;i++)scanf("%d",&x),modify(rt[1],1,n,i,x);id++;while(m--){int f,p,x,y,t,q,k;scanf("%d",&f);if(!f){scanf("%d%d%d",&p,&x,&y);LL l=quary(rt[p],1,n,1,y),r=quary(rt[p],1,n,x,y);int tmp=0;split(rt[p],tmp,l); split(rt[p],rt[++id],l-r); merge(rt[p],tmp);}else if(f==1){scanf("%d%d",&p,&t);merge(rt[p],rt[t]);}else if(f==2){scanf("%d%d%d",&p,&x,&q);modify(rt[p],1,n,q,x);}else if(f==3){scanf("%d%d%d",&p,&x,&y);printf("%lld\n",quary(rt[p],1,n,x,y));}else {scanf("%d%lld",&p,&k);printf("%d\n",val[rt[p]]>=k?quary(rt[p],1,n,k):-1);}}return 0; }總結
以上是生活随笔為你收集整理的线段树动态开点 - - - > 线段树合并的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《虚拟化安全解决方案》一2.2 配置VM
- 下一篇: F - Parenthesis Chec