實驗1:SDN拓撲實驗
阿新 • • 發佈:2021-09-07
線段樹分裂
給自己看的,就挑一下重點
需要動態開點……
用 \(\rm new\) 函式的話也沒什麼,不過不能寫回收棧了,直接 \(\rw delete\) 即可
\(split\)
類似於主席樹,直接指標指過去即可,記得要把原指標清掉
剩下的細節都在程式碼裡寫了
#include <bits/stdc++.h> using namespace std; #define int long long const int mod = 1e9 + 7; template<typename _T> inline void read(_T &x) { x = 0;int f= 1;char s = getchar(); while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();} x*=f; } const int np = 2e5 + 5; int ind = 1; struct Node{ int l,r; Node *ls,*rs; int num; Node(int L,int R) { l = L,r = R; ls = rs = NULL; num = 0; } inline bool inrange(int L,int R){return L<=l&&r<=R;} inline bool outofrange(int L,int R){return r<L||R<l;} inline void pushdown() { int mid = l+r>>1; if(!ls) ls = new Node(l , mid); if(!rs) rs = new Node(mid + 1 , r); } inline void pushup() { int ln=0,rn=0; if(l == r) return;//這個一定得判,不然到葉子節點會掛 if(ls) ln = ls->num; if(rs) rn = rs->num; num = ln + rn; } inline void insert(int x,int val) { if(inrange(val,val)) { num+=x; return; } else { if(!outofrange(val,val)) { pushdown(); ls->insert(x,val); rs->insert(x,val); pushup(); } return ; } } inline int query(int kth)//線段樹上二分 { if(kth > num) return -1; if(!ls && !rs) { return l; } else { int ln=0; if(ls) ln = ls->num; if(kth <= ln) return ls->query(kth); else return rs->query(kth - ln); } } inline int query(int L,int R) { if(inrange(L,R)) { return num; } else { if(!outofrange(L,R)) { int ln = 0,rn = 0; if(ls) ln = ls->query(L,R); if(rs) rn = rs->query(L,R); return ln + rn; } else return 0; } } }*rot[np + 10]; inline Node *merge(Node *u ,Node *&pre,int l,int r) { if(!pre) return u; if(!u) return pre; u->num += pre->num; int mid = l+r>>1; u->ls = merge(u->ls , pre->ls , l , mid); u->rs = merge(u->rs , pre->rs , mid + 1 , r); delete(pre);//空間卡的緊的話能刪就刪 pre = NULL; u->pushup();//一定要上傳! return u; } inline void split(Node *u , Node *&pre,int L,int R)//pre傳指標的地址 { if(pre->inrange(L,R)) { *u = *pre; pre = NULL; return; } else { if(!pre->outofrange(L,R)) { int l = pre->l , r = pre->r; int mid = l + r >> 1; if(pre->ls) split(u->ls = new Node(l,mid), pre->ls , L,R); if(pre->rs) split(u->rs = new Node(mid+1,r), pre->rs , L,R); if(!pre->ls && !pre->rs) pre = NULL;//記得判NULL else pre->pushup(); u->pushup();//一定要上傳 } else return ; } } signed main() { int n,m; read(n); read(m); rot[ind] = new Node(1,n); for(int i=1,x;i<=n;i++) { read(x); rot[ind]->insert(x , i); } for(int i=1,p,x,y,t,opt,q,k;i<=m;i++) { read(opt); switch(opt) { case 0:{ read(p); read(x); read(y); rot[++ind] = new Node(1,n); if(!rot[p]) continue; split(rot[ind],rot[p],x,y); break; } case 1:{ read(p); read(t); rot[p] = merge(rot[p],rot[t],1,n); break; } case 2:{ read(p); read(x); read(q); if(!rot[p]) rot[p] = new Node(1,n); rot[p]->insert(x,q); break; } case 3:{ read(p); read(x); read(y); if(!rot[p]) { printf("0\n"); continue; } int la = rot[p]->query(x,y); printf("%lld\n",la); break; } case 4:{ read(p); read(k); if(!rot[p]) { printf("-1\n"); continue; } int la = rot[p]->query(k); printf("%lld\n",la); break; } } } }