樹鏈剖分 講解+模板+習題

今天我們來講一下樹鏈剖分

樹鏈剖分是什么?

樹鏈剖分是一種用來維護樹上路徑信息的在線方法,可以處理在線。

通常通過一種方法,將一棵樹剖分成若干條鏈,然后通過數據結構(線段樹,BIT等)去維護。

我們通常所說的樹鏈剖分,基本都是輕重鏈剖分。

下面我們介紹一下這一種剖分。

學習樹鏈剖分的基礎知識有lca,dfs序,線段樹等。

首先,我們來明確即可變量。

\(size_i\)表示以\(i\)為子樹的大小,包括\(i\)

\(heavy_i\)表示\(i\)的所有兒子\(j\)\(size_j\)最大的一個

連接\(i\)\(heavy_i\)的邊稱為重邊(\(heavy\) \(edges\)),其余為輕邊(\(light\) \(edges\))

當好多條重邊首尾相連,形成了一條更大的重邊時,我們稱這個重邊的集合叫重鏈(\(heavy\) \(path\)

因為不可能有兩條重鏈相交(根據重鏈定義可知),所以整棵樹被劃分成了若干條互不相交的重鏈。

舉個例子

HLD

紅色的邊是重邊,黑色是輕邊。1-2-4-8-16構成了一條重鏈。

其中所有的重鏈都不相交

再給一些剖分的性質。

  1. 每個點只屬于一個重鏈。
  2. 不可能有兩條重鏈相鄰。
  3. 從一個點開始,重復"重鏈頂端-->跳一條輕邊"這個過程,必定能到根
  4. 按上述方法跳,必定能在\(O(logn)\)步到達頂點。

給一下第4條的證明。

如果一條邊是重鏈,那他一次肯定能跳到重鏈頂端,這樣很快,

而沒經過一條輕邊,根據重鏈的定義,輕邊所在子樹\(size\)< \(\frac{1}{2}\) 所有子樹\(size\) ,則沒經過一條輕邊,該點得子樹大小必定\(*2\)甚至更多,則只會有\(O(logn)\)次。

那我們怎么通過代碼處理輕重邊剖分?

一種經典的處理方法如下。


\(father_x\)表示\(x\)的父親節點
\(size_x\)表示\(x\)的子樹大小
\(deep_x\)表示\(x\)的深度
\(heavy_x\)表示\(x\)的重兒子
\(top_x\) 表示\(x\)的重鏈頂點

處理以上幾個數組通常使用兩遍dfs處理。

第一次構建前4個數組

第二次本質是對重鏈進行標號與整理

每次遍歷到某點時,先遞歸它的重兒子,

在遞歸他的輕兒子,它的重鏈頂端就是自己

順便處理\(top_x\)

兩遍dfs代碼:

void dfs1(int rt){size[rt]=1;for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt]) continue ; fa[to]=rt;dep[to]=dep[rt]+1 ;//信息 dfs1(to) ;size[rt]+=size[to] ;if (!hson[rt] || size[to]>size[hson[rt]]) hson[rt]=to ;//處理重兒子 }
} 
void dfs2(int rt,int t){top[rt]=t ;if (!hson[rt]) return ;dfs2(hson[rt],t) ;//先遞歸重兒子 for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt] || to==hson[rt]) continue ;dfs2(to,to) ;//輕邊頂端為自己 }
}

之后,我們用線段樹維護每條重鏈的信息(在實際操作中,輕邊也算作重鏈)

在此同時,我們需要記錄每個節點的時間戳\(dfn_x\),同樣最好記錄每個\(dfn_x\)對應的節點,我們用\(seq_x\)表示。

這兩個操作也非常簡單,只需在dfs2初始時加這兩句話:

    dfn[rt]=++tot ;seq[tot]=rt ;

因為我們是先處理重兒子的,所以重鏈的節點肯定會被放在線段樹的同一個區間中,這樣方便線段樹操作。

之后上面的剖分過程大體就結束了。

樹鏈剖分能夠暴力求出兩兩點的\(lca\)

為何說暴力,因為它不像倍增一樣要枚舉\(2^j\)步,他就是每次跳,而且時間復雜度有保障!

我們來講一講這個過程。

先上一張圖

slpf

如果要查詢9和11的lca,我們手動模擬一下:

1.首先11的dep較大,11跳至1(\(fa[top[11]]\)
因為\(top[9]=top[11],\)所以結束循環,判定深度小的位\(lca\)即可

void lca(int x,int y){int fx=top[x],fy=top[y] ;while(fx!=fy){if (dep[x]<dep[y]){ //跳x swap(x,y) ;swap(fx,fy) ;}x=fa[fx];fx=top[x] ;}if (dep[x]>dep[y]) swap(x,y) ;return y ;
} 

了解了樹剖解救lca的過程,基本你已經掌握了樹剖了,只差來幾道例題,我們不妨講解幾道例題,更深入了解樹剖一下。

我們拿BZOJ 1036 樹的統計 舉個例子。

它讓你動態干三件事:

  1. 把某個點的權值改成t
  2. 詢問x到y的路徑上的節點權值的最大值
  3. 詢問x到y的路徑上的所以節點權值的和

這是一個樹鏈剖分的裸題。

他讓我們動態維護兩兩點的路徑信息。

假設我們剖分寫好了,線段樹也建好了,我們該怎么求出x到y的路徑上的節點權值的最大值和總和呢?

舉個例子。

slpf2

同樣是9和11的例子。

11跳到1,我們已經維護2~11的最大值和和,為3和6

之后維護1到9的最大值和和,為5和10

MAX=5 SUM=16

int linkmax(int x,int y){ //鏈上最大值int fx=top[x],fy=top[y],ans=-inf ;while(fx!=fy){if (dep[fx]<dep[fy]){swap(x,y) ;swap(fx,fy) ;} ans=max(ans,qmax(1,dfn[fx],dfn[x])) ;x=fa[fx] ;fx=top[x] ;}if (dep[x]>dep[y]) swap(x,y) ;//在同一條重鏈上 ans=max(ans,qmax(1,dfn[x],dfn[y])) ;return ans ;
}
int linksum(int x,int y){ //鏈上和int fx=top[x],fy=top[y],ans=0 ;while(fx!=fy){if (dep[fx]<dep[fy]){swap(x,y) ;swap(fx,fy) ;}ans+=qsum(1,dfn[fx],dfn[x]) ;x=fa[fx] ;fx=top[x] ;}if (dep[x]>dep[y]) swap(x,y) ;ans+=qsum(1,dfn[x],dfn[y]) ;return ans ;
}

建議自己手動模擬一下,對于理解算法有很大作用

代碼:

#include <bits/stdc++.h>
using namespace std ;
const int N = 30010 ;
const int inf = (1<<30) ;
#define rep(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define REP(i,a,b) for (int (i)=(a);(i)>=(b);(i)--)
#define ls ((rt)<<1)
#define rs ((rt)<<1|1)
typedef long long ll ;vector <int> e[N] ;
int a[N],size[N],fa[N],dep[N],hson[N],top[N],dfn[N],seq[N] ;
int n,Q,tot,x,y,u,t ;
char op[20] ;struct node{int l,r,Max,sum;}tr[N<<2];void dfs1(int rt){size[rt]=1;for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt]) continue ; fa[to]=rt;dep[to]=dep[rt]+1 ;dfs1(to) ;size[rt]+=size[to] ;if (!hson[rt] || size[to]>size[hson[rt]]) hson[rt]=to ;}
} 
void dfs2(int rt,int t){top[rt]=t ;dfn[rt]=++tot ;seq[tot]=rt ;if (!hson[rt]) return ;dfs2(hson[rt],t) ;for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt] || to==hson[rt]) continue ;dfs2(to,to) ;}
}
inline void pushup(int rt){tr[rt].Max=max(tr[ls].Max,tr[rs].Max) ;tr[rt].sum=tr[ls].sum+tr[rs].sum ;
} 
void build(int rt,int l,int r){tr[rt].l=l;tr[rt].r=r ;if (l==r){tr[rt].Max=tr[rt].sum=a[seq[l]] ;return ; }int mid=(l+r)>>1;build(ls,l,mid) ;build(rs,mid+1,r) ;pushup(rt) ;
}
void modify(int rt,int pos){if (tr[rt].l==tr[rt].r){tr[rt].Max=tr[rt].sum=a[seq[tr[rt].l]] ;return ;}int mid=(tr[rt].l+tr[rt].r)>>1 ;if (pos<=mid) modify(ls,pos) ;else modify(rs,pos) ;pushup(rt) ;
}
int qmax(int rt,int l,int r){if (l<=tr[rt].l && tr[rt].r<=r) return tr[rt].Max ;int mid=(tr[rt].l+tr[rt].r)>>1 ;if (r<=mid) return qmax(ls,l,r) ;if (l>mid) return qmax(rs,l,r) ;return max(qmax(ls,l,r),qmax(rs,l,r)) ;
} 
int qsum(int rt,int l,int r){if (l<=tr[rt].l && tr[rt].r<=r) return tr[rt].sum ;int mid=(tr[rt].l+tr[rt].r)>>1 ;if (r<=mid) return qsum(ls,l,r) ;if (l>mid) return qsum(rs,l,r) ;return qsum(ls,l,r)+qsum(rs,l,r) ;
}
int linkmax(int x,int y){int fx=top[x],fy=top[y],ans=-inf ;while(fx!=fy){if (dep[fx]<dep[fy]){swap(x,y) ;swap(fx,fy) ;} ans=max(ans,qmax(1,dfn[fx],dfn[x])) ;x=fa[fx] ;fx=top[x] ;}if (dep[x]>dep[y]) swap(x,y) ;//在同一條重鏈上 ans=max(ans,qmax(1,dfn[x],dfn[y])) ;return ans ;
}
int linksum(int x,int y){int fx=top[x],fy=top[y],ans=0 ;while(fx!=fy){if (dep[fx]<dep[fy]){swap(x,y) ;swap(fx,fy) ;}ans+=qsum(1,dfn[fx],dfn[x]) ;x=fa[fx] ;fx=top[x] ;}if (dep[x]>dep[y]) swap(x,y) ;ans+=qsum(1,dfn[x],dfn[y]) ;return ans ;
}
int main(){scanf("%d",&n) ;for (int i=1;i<n;i++){scanf("%d%d",&x,&y) ;e[x].push_back(y) ; e[y].push_back(x) ;}for (int i=1;i<=n;i++) scanf("%d",&a[i]) ;fa[1]=0;dep[1]=1; dfs1(1) ;dfs2(1,1) ;build(1,1,n) ;scanf("%d",&Q) ;while(Q--){scanf("%s%d%d",op,&u,&t) ;if (op[0]=='C') a[u]=t,modify(1,dfn[u]) ;else if (op[1]=='M') printf("%d\n",linkmax(u,t)) ;else if (op[1]=='S') printf("%d\n",linksum(u,t)) ;}
}

一道雙倍經驗題:【模板】樹鏈剖分

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const int N = 100010 ;
#define int long long
struct edge{int to,next ;
}e[N<<1];
int head[N],f[N],dep[N],size[N],son[N],rk[N],top[N],dfn[N];
int a[N];
//f[i]:i的父親,dep[i]:i的深度,size[i]:i的子樹大小,son[i]:重兒子 ,rk[i]:i的dfs值,與dfn相反
//top[i]:i所在鏈的頂端,dfn[i]:dfs序,時間戳 
int n,m,rt,tot,cnt;
int p,r ;
inline void add(int x,int y){e[++cnt].to=y;e[cnt].next=head[x] ;head[x]=cnt ;
}
void dfs1(int rt,int fa,int depth){ //主要處理深度,父親和兒子 f[rt]=fa;dep[rt]=depth;size[rt]=1;//一些初始化 for (int i=head[rt];i;i=e[i].next){int to=e[i].to ;if (to==fa) continue ;//保證不是父親 dfs1(to,rt,depth+1) ;size[rt]+=size[to] ;//rt的大小+子樹的大小 if (size[son[rt]]<size[to]) son[rt]=to ;//改變重兒子 }return ;
}
void dfs2(int rt,int t){ //主要處理鏈,dfs序 top[rt]=t;dfn[rt]=++cnt;rk[cnt]=rt;//初始化if (!son[rt]) return ;//該點沒有重兒子 dfs2(son[rt],t) ;//rt的重兒子也是和rt一樣處于以t為頂端的重鏈 for (int i=head[rt];i;i=e[i].next){int to=e[i].to ;if (to!=f[rt] && to!=son[rt]) dfs2(to,to) ;//一個點位于輕鏈底端,那么它的top必然是它本身}return ;
}
struct seg{ //線段樹 int ls,rs,lazy,l,r;int sum ;
}tree[N<<1];
inline void pushup(int rt){tree[rt].sum=(tree[tree[rt].ls].sum+tree[tree[rt].rs].sum+tree[rt].lazy*(tree[rt].r-tree[rt].l+1))%p;return ;
}
void build(int ll,int rr,int rt){ //createif (ll==rr){tree[rt].l=tree[rt].r=ll ;tree[rt].sum=a[rk[ll]] ;return ;}else {int mid=(ll+rr)>>1;tree[rt].ls=cnt++ ;tree[rt].rs=cnt++ ;build(ll,mid,tree[rt].ls) ;build(mid+1,rr,tree[rt].rs) ;tree[rt].l=tree[tree[rt].ls].l ;tree[rt].r=tree[tree[rt].rs].r ;pushup(rt) ;}return ;
}
void update(int l,int r,int rt,int c){ //l~r +c if (l<=tree[rt].l && tree[rt].r<=r) {tree[rt].sum=(tree[rt].sum+c*(tree[rt].r-tree[rt].l+1))%p ;tree[rt].lazy=(tree[rt].lazy+c)%p ;}else {int mid=(tree[rt].l+tree[rt].r)>>1 ;if (l<=mid) update(l,r,tree[rt].ls,c) ;if (mid<r) update(l,r,tree[rt].rs,c) ;pushup(rt) ;}return ;
}
int query(int l,int r,int rt){if (l<=tree[rt].l && tree[rt].r<=r) return tree[rt].sum ;int tot=(tree[rt].lazy*(min(r,tree[rt].r)-max(l,tree[rt].l)+1)%p)%p ;//初始值int mid=(tree[rt].l+tree[rt].r)>>1 ;if (l<=mid) tot=(tot+query(l,r,tree[rt].ls))%p ;if (mid<r)  tot=(tot+query(l,r,tree[rt].rs))%p ;return tot%p ; 
} 
inline int sum(int x,int y){int ans=0;int fx=top[x],fy=top[y] ;while (fx!=fy){if (dep[fx]>=dep[fy]) {ans=(ans+query(dfn[fx],dfn[x],rt))%p ;x=f[fx],fx=top[x] ;}else {ans=(ans+query(dfn[fy],dfn[y],rt))%p ;y=f[fy],fy=top[y] ;}} if (dfn[x]<=dfn[y]) ans=(ans+query(dfn[x],dfn[y],rt))%p ;else ans=(ans+query(dfn[y],dfn[x],rt))%p ;return ans%p ;
}
inline void UPDATE(int x,int y,int c){int fx=top[x],fy=top[y];while(fx!=fy){if(dep[fx]>=dep[fy]){update(dfn[fx],dfn[x],rt,c) ;x=f[fx],fx=top[x];}else {update(dfn[fy],dfn[y],rt,c) ;y=f[fy],fy=top[y];}}if (dfn[x]<=dfn[y]) update(dfn[x],dfn[y],rt,c) ;else update(dfn[y],dfn[x],rt,c) ;return ;
}
main(){scanf("%lld%lld%lld%lld",&n,&m,&r,&p) ;for (int i=1;i<=n;i++) scanf("%lld",&a[i]) ;for (int i=1;i<n;i++){int x,y ;scanf("%lld%lld",&x,&y) ;add(x,y);add(y,x) ;}cnt=0 ;dfs1(r,0,1) ;dfs2(r,r) ;cnt=0;rt=cnt++ ;build(1,n,rt);
//  return 0 ; for (int i=1;i<=m;i++){//   cout<<i<<endl ;int x,y,op ;int z ;scanf("%lld",&op);if (op==1){scanf("%lld%lld%lld",&x,&y,&z) ;UPDATE(x,y,z) ; }else if (op==2){scanf("%lld%lld",&x,&y) ;printf("%lld\n",sum(x,y)) ;}else if (op==3){scanf("%lld%lld",&x,&z) ;update(dfn[x],dfn[x]+size[x]-1,rt,z) ; }else {scanf("%lld",&x) ;printf("%lld\n",query(dfn[x],dfn[x]+size[x]-1,rt)) ;}}
}

再來一道例題。

BZOJ 4196 NOI2015 軟件包管理器

這個問題是動態刪鏈,動態加鏈的過程。

這題其實比上題還簡單,直接維護線段樹即可。

#include <bits/stdc++.h>
using namespace std ;
const int N = 100010 ;
const int inf = (1<<30) ;
#define rep(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define REP(i,a,b) for (int (i)=(a);(i)>=(b);(i)--)
#define ls ((rt)<<1)
#define rs ((rt)<<1|1)typedef long long ll ;vector <int> e[N] ;
int size[N],fa[N],dep[N],top[N],hson[N],dfn[N] ;
int n,m,tot,x ;
char op[20] ;
struct node{int l,r,sum,lazy ;
}tr[N<<2];void dfs1(int rt){size[rt]=1 ;for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt]) continue ;fa[to]=rt;dep[to]=dep[rt]+1; dfs1(to) ;size[rt]+=size[to] ;if (!hson[rt] || size[to]>size[hson[rt]]) hson[rt]=to ;}
}void dfs2(int rt,int t){top[rt]=t;dfn[rt]=++tot;if (!hson[rt]) return ;dfs2(hson[rt],t) ;for (int i=0;i<e[rt].size();i++){int to=e[rt][i] ;if (to==fa[rt] || to==hson[rt]) continue ;dfs2(to,to) ;}
}
inline void pushup(int rt){tr[rt].sum=tr[ls].sum+tr[rs].sum ;
}
void build(int rt,int l,int r){tr[rt].l=l;tr[rt].r=r,tr[rt].lazy=-1;if (l==r) return ;int mid=(l+r)>>1 ;build(ls,l,mid) ;build(rs,mid+1,r) ;pushup(rt) ;
}
inline void pushdown(int rt){ if (tr[rt].lazy==-1) return ;tr[ls].sum=tr[rt].lazy*(tr[ls].r-tr[ls].l+1) ;tr[rs].sum=tr[rt].lazy*(tr[rs].r-tr[rs].l+1) ;tr[ls].lazy=tr[rt].lazy ;tr[rs].lazy=tr[rt].lazy ;tr[rt].lazy=-1 ;
}
void modify(int rt,int l,int r,int c){  if (l<=tr[rt].l && tr[rt].r<=r) {tr[rt].sum=c*(tr[rt].r-tr[rt].l+1) ;tr[rt].lazy=c ;return ;}pushdown(rt) ; int mid=(tr[rt].l+tr[rt].r)>>1 ;if (l<=mid) modify(ls,l,r,c) ;if (r>mid) modify(rs,l,r,c) ;pushup(rt) ;
}
int query(int rt,int l,int r){if (l<=tr[rt].l && tr[rt].r<=r) return tr[rt].sum ;pushdown(rt) ;int res=0,mid=(tr[rt].l+tr[rt].r)>>1 ;if (l<=mid) res+=query(ls,l,r) ;if (r>mid) res+=query(rs,l,r) ;return res ;
}
int sum(int x){int ans=0,fx=top[x] ;while (fx!=1){ans+=dfn[x]-dfn[fx]-query(1,dfn[fx],dfn[x])+1 ;modify(1,dfn[fx],dfn[x],1) ;x=fa[fx] ;fx=top[x] ;}ans+=dfn[x]-dfn[1]-query(1,dfn[1],dfn[x])+1 ;modify(1,dfn[1],dfn[x],1) ;return ans ;
}
int main(){scanf("%d",&n) ;for (int i=2;i<=n;i++) {scanf("%d",&x) ;x++ ; e[x].push_back(i) ;e[i].push_back(x) ;}fa[1]=0;dep[1]=1 ;dfs1(1) ;dfs2(1,1) ;build(1,1,n) ;scanf("%d",&m) ;for (int i=1;i<=m;i++){scanf("%s%d",&op,&x) ;x++ ;if (op[0]=='i') printf("%d\n",sum(x)) ;else {printf("%d\n",query(1,dfn[x],dfn[x]+size[x]-1)) ;modify(1,dfn[x],dfn[x]+size[x]-1,0) ;}}
}

都理解了, 來幾道習題練練

Aragorn's Story

[HAOI2015]樹上操作

月下“毛景樹”

蒟蒻第一次寫關于算法的博客,有問題或建議請及時提出,在評論區中發表,博主將及時更改,謝謝閱讀!

轉載于:https://www.cnblogs.com/harryhqg/articles/9445408.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451708.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451708.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451708.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

navicat 批量插入 測試數據

1. 前言 遇到線上大sql執行較慢, 10s, 做優化改進時&#xff0c;首先想到的是在本地造出一個類似的庫環境&#xff0c;先本地實驗。 然后往表中創建大量數據... 2. 方案 利用mysql函數來插入大量數據 代碼 BEGIN#Routine body goes here... DECLARE id int; DECLARE driverid …

互聯網產品用戶體驗設計的三大定律

好友發過來一PPT&#xff0c;文件名是互聯網產品的體驗設計&#xff0c;認真看完&#xff0c;收獲頗多&#xff0c;其中印象最深刻的是用戶體驗可用性的三大定律&#xff0c;正好FasterSoft正在打造互聯網精品平臺iWorld&#xff0c;最需要的時候好東西就上門來了&#xff0c;這…

oracle 對應的JDBC驅動 版本

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Oracle版本jdk版本推薦jar包備注Oracle 8iJDK 1.1.xclasses111.zip Oracle 8iJDK 1.1.xclasses12.zip Oracle 9iJDK 1.1.xclasses111.ja…

JSP特點

1.JSP文件必須在JSP服務器內運行。 2.JSP文件必須生成servlet才能執行。 3.JSP頁面的第一個訪問者速度慢&#xff0c;因為需要編譯生成Servlet。 4.JSP不需要專門的客戶端&#xff0c;也不需要java運行環境&#xff0c;因為JSP輸出到頁面是標準的HTML文件。

35--用兩個棧實現隊列

1.問題描述 用兩個棧實現一個隊列。隊列的聲明如下&#xff0c;請實現它的兩個函數 appendTail 和 deleteHead &#xff0c;分別完成在隊列尾部插入整數和在隊列頭部刪除整數的功能。(若隊列中沒有元素&#xff0c;deleteHead 操作返回 -1 ) 示例 1&#xff1a; 輸入&#xf…

如何open一個新tab頁面

打開新tab頁的兩種方式 1 a標簽 function openwin(url) {var a document.createElement("a");a.setAttribute("href", url);a.setAttribute("target", "_blank");a.setAttribute("id", "camnpr");document.body.…

Linux中打開文件管理器的命令

在Mac中&#xff0c;我們可以使用open命令&#xff0c;在終端打開指定目錄下的文件管理器&#xff0c;在Linux中&#xff0c;同樣可以使用類似的命令&#xff1a;nautilus。 轉載于:https://www.cnblogs.com/chaoguo1234/p/9446106.html

final類與方法

final類---不可被繼承。 final方法---不可被覆蓋。

【Visual C++】一些開發心得與調試技巧

自己平時收集的一些技巧與心得&#xff0c;這里分享出來&#xff0c;普及一下知識。 1.如何在Release狀態下進行調試   Project->Setting>ProjectSetting對話框&#xff0c;選擇Release狀態。C/C標簽中的Category選General&#xff0c;Optimizations選Disable(Debug)&a…

36--斐波那契數列

1. 問題描述 寫一個函數&#xff0c;輸入n&#xff0c;求斐波那契&#xff08;Fibonacci&#xff09;數列的第 n 項。斐波那契數列的定義如下&#xff1a; F(0) 0, F(1) 1 F(N) F(N - 1) F(N - 2), 其中 N > 1. 斐波那契數列由 0 和 1 開始&#xff0c;之后的斐波那契數…

lineNumber: 1; columnNumber: 1; 前言中不允許有內容

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我是在xml配置文件中引用別的配置文件&#xff0c;本來是這樣寫的 <import resource"spring-mybatis.xml" /> 就報這…

idea輸入法候選區不跟隨光標

環境&#xff1a; win10 idea 2017.04 搜狗8.6 問題&#xff1a; idea編輯區輸入法候選區不跟隨光標 解決&#xff1a; 輸入法改成必應輸入法 不行的話不用你動手 我自砸蛋蛋。&#xff08;保命狗頭。。&#xff09; 轉載于:https://www.cnblogs.com/yadongliang/p/9079367.htm…

C# 反射 (Reflect)

# C# 反射 &#xff08;Reflect&#xff09; 1.基本內容 我們可以使用反射動態地創建類型的實例&#xff0c;將類型綁定到現有對象&#xff0c;或從現有對象中獲取類型。然后&#xff0c;可以調用類型的方法或訪問其字段和屬性。 最基本的調用&#xff1a; Assembly assembly …

jsp中的%@ ...%

主要用來提供整個JSP 網頁相關的信息&#xff0c;并且用來設定JSP網頁的相關屬性

37--計算一個字符串中每個字符出現次數

1.問題描述 需求&#xff1a;計算一個字符串中每個字符出現次數。 2.解題思路 獲取一個字符串對象&#xff1b;創建一個Map集合&#xff0c;鍵代表字符&#xff0c;值代表次數&#xff1b;遍歷字符串得到每個字符&#xff1b;判斷Map中是否有該鍵&#xff1b;如果沒有&#…

oracle thin和oci 區別

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Features of Oracle JDBC Drivers&#xff1a; 1.JDBC Oci 此驅動類似于傳統的ODBC 驅動。因為它需要Oracle Call Interface and Net8&…

從拿到班車手冊.xls到搜索附近班車地點

起因 七月份要去某廠報道了&#xff0c;異地租房的時候發現想租一個有公司班車的地方&#xff0c;卻不知道哪里有班車。輾轉流傳出班車手冊后發現搜索實在是太不方便了&#xff0c;于是有了一個主義&#xff0c;想做一個可以搜索房子地址&#xff0c;找出附近班車點&#xff08…

2018.08.09洛谷P3959 寶藏(隨機化貪心)

傳送門 回想起了自己賽場上亂搜的20分。 好吧現在也就是寫了一個隨機化貪心就水過去了&#xff0c;不得不說隨機化貪心大法好。 代碼&#xff1a; #include<bits/stdc.h> using namespace std; inline int read(){int ans0;char chgetchar();while(!isdigit(ch))chget…

AWT和Swing

AWT 是Abstract Window ToolKit (抽象窗口工具包)的縮寫&#xff0c;這個工具包提供了一套與本地圖形界面進行交互的接口。AWT 中的圖形函數與操作系統所提供的圖形函數之間有著一一對應的關系&#xff0c;我們把它稱為peers。 也就是說&#xff0c;當我們利用 AWT 來構件圖形用…

解決 : Apache Tomcat/8.0.0-RC1 - Error report ... HTTP Status 404

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.報錯&#xff1a; Apache Tomcat/8.0.0-RC1 - Error report HTTP Status 404 - /richer/getOnLineRicherCount The requested resour…