目錄spa
本文將記錄一些奇技淫巧和板子(最基礎的也有),先從今天開始寫,之前的找個時間再補上code
應用快速排序思想(\(O(n)\)),日常都是\(O(nlogn)\)
基於快排的思想,在每一層遞歸中,隨機選取一個數作基準時,統計出大於基準值的數的個數\(cnt\),若是\(k<=cnt\)就在左半段(比基準數大)中尋找第\(k\)大的數,反之則在右半段尋找第\(k-cnt\)大的數排序
複雜度證實:遞歸
由於每次只進入了左右兩段的任意一個,則在平均狀況之下複雜度爲:\(n+\frac{n}{2}+\frac{n}{3}+.....+1=O(n)\)it
預處理class
void st_prework() { for(int i=1; i<=n; ++i) f[i][0]=a[i]; for(int j=1; j<=21; ++j) for(int i=1; i+(1<<j)-1<=n; ++i) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); }
查詢基礎
int query(int l,int r) { int res=-9999; int k=0; while((1<<(k+1)<=r-l+1)) k++; res=max(f[l][k],f[r-(1<<k)+1][k]); return res; }
開兩個棧,a存原始數據,b存歷史上每一個時刻的最小值
舉個例子
a:9 2 1 5 3 0 2 <-
b:9 2 1 1 1 0 0 <-
每次插入元素x時,a插入x,b插入min(top(b),x),彈出時一塊兒彈,詢問時輸出top(b)遍歷
以前用的二分太傻比了,須要考慮的東西太多(但是我沒有腦子),學長就教了一個咕咕咕的二分queue
int l=0,r=1e18;//取個大一點的數 while(l<=r) { int mid=(l+r)>>1; if(check(mid)) r=mid-1,ans=mid; else l=mid+1; } cout<<ans;
double l=0,r=1e18;//取個大一點的數 while(r-l<=eps) { double mid=(l+r)/2; if(check(mid)) r=mid,ans=mid; else l=mid; } cout<<ans;
//dfs void dfs(int x) { visit[x]=1; for(int i=head[x];i;i=e[i].Next) { int to=e[i].v; if(visit[to]) continue; dfs(to); } } //bfs void bfs() { queue<int>q; q.push(1); d[1]=1;//層數 while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].Next) { int to=e[i].v; if(visit[to]) continue; d[to]=d[u]+1; q.push(to); } } }
dfs序的特色:統計
每一個節點x編號在序列中出現兩次,並且以這兩次出現位置爲端點的閉區間就是以x爲根的子樹的DFS序
void dfs(int x) { a[++len]=x;//記錄dfs序 visit[x]=1; for(int i=head[x];i;i=e[i].Next) { int to=e[i].v; if(visit[to]) continue; dfs(to); } a[++len]=x; }
void dfs(int x) { int max_part=0;//刪除掉x後最大子樹大小 size[x]=1;//子樹x的大小 visit[x]=1; for(int i=head[x];i;i=e[i].Next) { int to=e[i].v; if(visit[to]) continue; dfs(to); size[x]+=size[y]; max_part=max(max_part,size[y]); } max_part=max(max_part,n-size[x]);//n爲整顆樹的節點數目 if(max_part<ans) { ans=max_part;//記錄重心對應的max_part值 pos=x;//記錄重心編號 } }
void dfs(int x) { visit[x]=cnt; for(int i=head[x];i;i=e[i].Next) { int to=e[i].v; if(visit[to]) continue; dfs(to); } } for(int i=1;i<=n;++i) if(!visit[i]) cnt++,dfs(i);
void topsort() { queue<int>q; for(int i=1;i<=n;++i) if(du[i]==0) q.push(i);//du在add時記錄 while(!q.empty()) { int u=q.front(); q.pop(); a[++len]=u;//記錄拓撲序 for(int i=head[u];i;i=e[i].Next) { int to=e[i].v; if(--du[to]==0) q.push(to); } } }
int * z=y+50 z[50]-->y[0]