線段樹就像一句話:node
聽過不少道理,卻依然過很差這一輩子。 ε(┬┬﹏┬┬)3c++
仍是總結一下線段樹的知識點。網上有不少模板,其中最突出的就不用說了,《線段樹徹底版》主要是沒怎麼學,沒怎麼去了解那個大佬的風格。git
這裏我記錄一下劉汝佳大牛的板子。ui
#include <bits/stdc++.h> using namespace std; const int maxnode = 1<<17;// maxnode = 2<<n - 1; const int INF = 0x3f3f3f3f; //點修改 int ql,qr; //查詢 int p,v; //A[p] = v; struct IntervalTree { int minv[maxnode]; void update(int o,int L,int R) { int M = L + (R-L)/2; if(L==R) minv[o] = v; else { if(p<=M) update(o*2,L,M); else update(o*2+1,M+1,R); } minv[o] = min(minv[o*2],minv[o*2+1]); } int query(int o,int L,int R) { int M = L + (R-L)/2,ans = INF; if(ql<=L&&R<=qr) return minv[o]; if(ql<=M) ans = min(ans,query(o*2,L,M)); if(M<qr) ans = min(ans,query(o*2+1,M+1,R)); return ans; } }; IntervalTree tree; int main() { int n,m; int op; while(scanf("%d%d",&n,&m)==2) { memset(&tree,0,sizeof(tree)); while(m--) { scanf("%d",&op); if(op==1) { scanf("%d%d",&p,&v); tree.update(1,1,n); } else { scanf("%d%d",&ql,&qr); printf("%d\n",tree.query(1,1,n)); } } } return 0; }
#include <bits/stdc++.h> using namespace std; //區間修改 // add(l,r,v) const int maxnode = 1<<17;// maxnode = 2<<n - 1; const int INF = 0x3f3f3f3f; int _min,_max,_sum; struct IntervalTree { int sumv[maxnode],minv[maxnode],maxv[maxnode],addv[maxnode]; void maintain(int o,int L,int R) { int lc = o*2,rc=o*2+1; sumv[o] = minv[o] = maxv[o] = 0; if(R>L) { sumv[o] = sumv[lc] + sumv[rc]; minv[o] = min(minv[lc],minv[rc]); maxv[o] = max(maxv[lc],maxv[rc]); } minv[o] +=addv[o]; maxv[o] +=addv[o]; sumv[o] +=addv[o]*(R-L+1); } void update(int o,int L,int R) { int lc = o*2,rc = o*2+1; if(ql<=L&&qr>=R) addv[o]+=v; else { int M = L + (R-L)/2; if(ql<=M) update(lc,L,M); if(qr>M) update(rc,M+1,R); } maintain(o,L,R); } void query(int o,int L,int R,int add) { if(ql<=L&&qr>=R) { _sum +=sumv[o] + add*(R-L+1); _min = min(_min,minv[o]+add); _max = max(_max,maxv[o]+add); } else { int M = L + (R-L)/2; if(ql<=M) query(o*2,L,M,add+addv[o]); if(qr>M) query(o*2+1,M+1,add+addv[o]); } } }; IntervalTree tree; int main() { int n,m,op; while(scanf("%d%d",&n,&m)==2) { memset(&tree,0,sizeof(tree)); scanf("%d%d%d",&op,&ql,&qr); if(op==1) { scanf("%d",&v); tree.update(1,1,n); } else { _sum = 0;_min=INF;_max = -INF; tree.query(1,1,n,0); printf("%d %d %d\n",_sum,_min,_max); } } return 0; }
#include <bits/stdc++.h> using namespace std; const int maxnode = 1<<17;// maxnode = 2<<n - 1; const int INF = 0x3f3f3f3f; int _min,_max,_sum; //區間修改 // set(l,r,v) A[l...r] = v; struct IntervalTree { int sumv[maxnode],minv[maxnode],maxv[maxnode],setv[maxnode]; //維護信息 void maintain(int o,int L,int R) { int lc = o*2,rc = o*2 + 1; if(R>L) { sumv[o] = sumv[lc] + sumv[rc]; minv[o] = min(minv[lc],minv[rc]); maxv[o] = max(maxv[lc],maxv[rc]); } if(setv[o]>=0) { minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o]*(R-L+1); } } //標記傳遞 void pushdown(int o) { int lc = o*2,rc = o*2 + 1; if(setv[o]>=0) { setv[lc] = setv[rc] = setv[o]; setv[o] = -1; } } void update(int o,int L,int R) { int lc = o*2,rc = o*2+1; if(ql<=L&&qr>=R) { setv[o] = v; } else { pushdown(o); int M = L + (R-L)/2; if(ql<=M) { update(lc,L,M); } else maintain(lc,L,M); if(qr>M) { update(rc,M+1,R); } else maintain(rc,M+1,R); } maintain(o,L,R); } void query(int o,int L,int R) { if(setv[o]>=o) { _sum +=setv[o]*(min(R,qr)-max(L,ql)+1); _min = min(_min,setv[o]); _max = max(_max,setv[o]); } else if(ql<=L&&qr>=R) { _sum +=sumv[o]; _min = min(_min,minv[o]); _max = max(_max,maxv[o]); } else { int M = L + (R-L)/2; if(ql<=M) query(o*2,L,M); if(qr>M) query(o*2+1,M+1,R); } } }; IntervalTree tree; int main() { int n,m,op; while(scanf("%d%d",&n,&m)==2) { memset(&tree,0,sizeof(tree)); memset(tree.setv,-1,sizeof(tree.setv)); tree.setv[1] = 0; while(m--) { scanf("%d%d%d",&op,&ql,&qr); if(op==1) { scanf("%d",&v); tree.update(1,1,n); } else { _sum = 0,_min = INF;_max = -INF; tree.query(1,1,n); printf("%d %d %d\n",_sum,_min,_max); } } } return 0; }
未完。。。spa
以前一直對劉汝佳的線段樹信心不大。是由於劉汝佳的板子沒有build操做,以致於初始化的時候,是O(nlogn),如今從新複習一下線段樹,找到了含有build操做的板子。code
這下線段樹的基本操做就已經差很少了!!!blog
#include <bits/stdc++.h> using namespace std; const int INF = 1000000000; const int maxnode = 1<<18; const int maxn = 100000+10; int A[maxn]; int op,qL,qR,p,v; //單點更新,建樹操做,A[p] = v; struct IntervalTree { int minv[maxnode]; void build(int o,int L,int R) { int M = L + (R-L)/2; if(L==R) minv[o] = A[L]; else { build(o*2,L,M); build(o*2+1,M+1,R); minv[o] = min(minv[o*2],minv[o*2+1]); } } void update(int o,int L,int R) { int M = L + (R-L)/2; if(L==R) minv[o] = v; else { if(p<=M) update(o*2,L,M); else update(o*2+1,M+1,R); minv[o] = min(minv[o*2],minv[o*2+1]); } } int query(int o,int L,int R) { int M = L + (R-L)/2,ans = INF; if(qL<=L&&R<=qR) return minv[o]; if(qL<=M) ans = min(ans,query(o*2,L,M)); if(M<qR) ans = min(ans,query(o*2+1,M+1,R)); return ans; } }; IntervalTree tree; int main(int argc, char const *argv[]) { //freopen("in.txt","r",stdin); int n,q; scanf("%d%d",&n,&q); memset(&tree,0,sizeof(tree)); for (int i = 1; i <= n; ++i) scanf("%d",&A[i]); tree.build(1,1,n); int k,args[20],original[20]; char cmd[100]; while(q--) { scanf("%s",cmd); int len = strlen(cmd); k = 0;args[k] = 0; for(int i=6; i < len; i++) { if(isdigit(cmd[i])) args[k] = args[k]*10 + cmd[i]-'0'; else { k++; args[k] = 0; } } if(cmd[0]=='q') { qL = args[0]; qR = args[1]; printf("%d\n", tree.query(1,1,n)); } else { for(int i=0; i < k; i++) original[i] = A[args[i]]; for(int i=0; i < k; i++) { p = args[i]; v = A[p] = original[(i+1)%k]; tree.update(1,1,n); } } } return 0; }