LeeShoWdian
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- type: slide --- <style> .reveal .slides { text-align: left; font-size:35px; } </style> ## 線段樹(1) Introduction to Competitive Programming 2/17 ---- - 介紹線段樹 - 單點加值 - 區間查詢 --- 線段樹是用來處理區間問題的一種資料結構 這堂課先講單點加值和區間查詢 區間加值下堂課會講 ---- ## 結構 線段樹的結構大概會長這樣: <center> <img src="https://hackmd.io/_uploads/HJnJ139tp.png" width="700px"> </center> ---- <center> <img src="https://hackmd.io/_uploads/S1pC1n5t6.png" width="700px"> </center> 我們會用陣列表示一顆線段樹 假設總共有$n$個數字 我們會用開以$4n$為長度的陣列 樹高為$logn$ ---- <center> <img src="https://hackmd.io/_uploads/S1pC1n5t6.png" width="700px"> </center> 當前節點的index為$i$ 左子節點為$2i$ 右子節點為$2i+1$ ---- <center> <img src="https://hackmd.io/_uploads/rJMMUhcFp.png" width="700px"> </center> 當前節點$i$有區間$[l,r]$ 定義$mid=(l+r)/2$ 左節點的區間為$[l,mid]$ 右節點的區間為$[mid+1,r]$ ---- 以下我們用這題來講解線段樹 給一個長度為$n$的陣列$a$,有$q$個操作,分為以下2種: - $1$ $l$ $r$ 詢問$[l,r]$區間的最大值 - $2$ $x$ $v$ 把$a_x$設為$v$ $1 \le n,q \le 2*10^5$ ---- <center> <img src="https://hackmd.io/_uploads/BJTslp9KT.png" width="700px"> </center> 假設當前陣列是a = [ 1, 5, 16, 7, 11, 4, 43, 15, 3] 當前節點$i$有區間$[l,r]$ 代表的是區間$[l,r]$內的最大值 ---- <center> <img src="https://hackmd.io/_uploads/BJTslp9KT.png" width="700px"> </center> 第$5$個節點表示區間$[3,4]$的最大值為$11$ 第$3$個節點表示區間$[5,8]$的最大值為$43$ ---- ## 建樹 可以發現葉節點的區間長度皆為1,以區間長度等於1為結束遞迴的條件 ```cpp! #define cl(x) (x<<1) #define cr(x) (x<<1)+1 void build(int id,int l,int r){ if(l==r){ seg[id]=arr[l]; return ; } int mid=(l+r)>>1; build(cl(id),l,mid); build(cr(id),mid+1,r); pull(id); } ``` ---- pull()為更新答案的函式 對於不同的答案他會長的些微不一樣 以區間求最大值而言: ```cpp! void pull(int id){ seg[id]=max(seg[cl(id)],seg[cr(id)]); } ``` ---- ## 區間查詢 給你一個區間$[sl,sr]$,你要如何快速找到這區間內的最大值 可以分成三種case去做: ---- 1. 當前區間$[l,r]$在$[sl,sr]$裏面,可以直接回傳這個區間的答案 <center> <img src="https://hackmd.io/_uploads/H1_i0Smc6.png" width="650px"> </center> 上圖$[l,r]$在$[sl,sr]$裏面,直接回傳$75$ ---- 2. 左邊區間有跟$[sl,sr]$交集到,有就往左遞迴 <center> <img src="https://hackmd.io/_uploads/S1fACHm9T.png" width="650px"> </center> 上面兩種case的左區間都有跟$[sl,sr]$交集到,要往左遞迴 ---- 3. 右邊區間有跟$[sl,sr]$交集到,有就往右遞迴 <center> <img src="https://hackmd.io/_uploads/By7QyIQ9p.png" width="650px"> </center> 上面兩種case的右區間都有跟$[sl,sr]$交集到,要往右遞迴 ---- 注意第2和第3的case是獨立的,以下情況2,3都會成立,左右兩邊都要遞迴: <center> <img src="https://hackmd.io/_uploads/ry0LyU7c6.png" width="650px"> </center> ---- 查詢$[2,7]$這個區間的最大值 <center> <img src="https://hackmd.io/_uploads/B1cNS8jK6.png" width="900px"> </center> ---- [0,8]左右兩個子區間都有跟[2,7]交集到 先往左遞迴 <center> <img src="https://hackmd.io/_uploads/HyfuU8otp.png" width="900px"> </center> ---- [0,4]左右兩個子區間都有跟[2,7]交集到 先往左遞迴 <center> <img src="https://hackmd.io/_uploads/B1r8PIiF6.png" width="900px"> </center> ---- [0,2]只有右邊子區間有跟[2,7]交集到 往右遞迴 <center> <img src="https://hackmd.io/_uploads/rycsPLsYa.png" width="900px"> </center> ---- 找到[2,2],[2,2]這個區間在[2,7]內,回傳這個區間的最大值 <center> <img src="https://hackmd.io/_uploads/HJSl_IjK6.png" width="900px"> </center> ---- 回到[0,4],因為右區間[3,4]有跟[2,7]交集到,往右遞迴 找到[3,4]這個區間在[2,7]內,回傳這個區間的最大值 <center> <img src="https://hackmd.io/_uploads/ByCut8oYT.png" width="900px"> </center> ---- 回到[0,8],因為右區間[5,8]有跟[2,7]交集到,往右遞迴 <center> <img src="https://hackmd.io/_uploads/rkOV5UjK6.png" width="900px"> </center> ---- [5,8]左右兩個子區間都有跟[2,7]交集到,先往左遞迴 然後找到[5,6]在[2,7]這個區間內,回傳這個區間的最大值 <center> <img src="https://hackmd.io/_uploads/S1eysUotp.png" width="900px"> </center> ---- 回到[5,8],因為右區間[7,8]有跟[2,7]交集到,往右遞迴 <center> <img src="https://hackmd.io/_uploads/SJSjj8sFa.png" width="900px"> </center> ---- [7,8],因為左區間[7,7]有跟[2,7]交集到,往左遞迴 因為[7,7]在[2,7]內,回傳這個區間的答案 <center> <img src="https://hackmd.io/_uploads/H1qM28iFp.png" width="900px"> </center> ---- 總共有[2,2],[3,4],[5,6],[7,7]這些區間 <center> <img src="https://hackmd.io/_uploads/H1qM28iFp.png" width="900px"> </center> ---- 實作查詢: ```cpp! int query(int id,int l,int r,int sl,int sr){ if(sl<=l&&r<=sr){//目前這個區間在查詢區間內 return seg[id]; } int mid=(l+r)>>1,res=0; if(sl<=mid){//左區間跟查詢區間有交集 res=max(res,query(cl(id),l,mid,sl,sr)); } if(mid<sr){//右區間跟查詢區間有交集 res=max(res,query(cr(id),mid+1,r,sl,sr)); } return res; } ``` 複雜度:$O(logn)$ ---- ### 單點修改 以剛剛那顆線段樹舉例 我們要修改區間[1,1]的值把5變成17 <center> <img src="https://hackmd.io/_uploads/BJTslp9KT.png" width="900px"> </center> ---- 首先先從跟節點遞迴找到[1,1]區間的節點 <center> <img src="https://hackmd.io/_uploads/H1nqzvsYT.png" width="900px"> </center> ---- 更改這個節點的值 <center> <img src="https://hackmd.io/_uploads/HyZZmPiKT.png" width="900px"> </center> ---- 由下往上更新經過的點的最大值 <center> <img src="https://hackmd.io/_uploads/B1PDXPjY6.png" width="900px"> </center> ---- 由下往上更新經過的點的最大值 <center> <img src="https://hackmd.io/_uploads/S1WAQPjKp.png" width="900px"> </center> ---- 由下往上更新經過的點的最大值 <center> <img src="https://hackmd.io/_uploads/rJnZVwjYp.png" width="900px"> </center> ---- 由下往上更新經過的點的最大值 <center> <img src="https://hackmd.io/_uploads/B1SLNwiYa.png" width="900px"> </center> ---- 更新完畢 <center> <img src="https://hackmd.io/_uploads/rJAuNwiF6.png" width="900px"> </center> ---- ### 實作單點更新 ```cpp! void update(int id,int l,int r,int x,int v){ if(l==r){//這時候l和r會等於x seg[id]=v; return ; } int mid=(l+r)>>1; if(x<=mid){ update(cl(id),l,mid,x,v); } if(mid<x){ update(cr(id),mid+1,r,x,v); } pull(id); } ``` 複雜度$O(logn)$ ---- 線段樹完整程式碼: ```cpp! #define cl(x) (x<<1) #define cr(x) (x<<1)+1 const int N; int seg[4*N]; void pull(int id){ seg[id]=max(seg[cl(id)],seg[cr(id)]) } void build(int id,int l,int r){ if(l==r){ seg[id]=arr[l]; return ; } int mid=(l+r)>>1; build(cl(id),l,mid); build(cr(id),mid+1,r); pull(id); } void update(int id,int l,int r,int x,int v){ if(l==r){ seg[id]=v; return ; } int mid=(l+r)>>1; if(x<=mid){ update(cl(id),l,mid,x,v); } if(mid<x){ update(cr(id),mid+1,r,x,v); } pull(id); } int query(int id,int l,int r,int sl,int sr){ if(sl<=l&&r<=sr){//目前這個區間在查詢區間內 return seg[id]; } int mid=(l+r)>>1,res=0; if(sl<=mid){//左區間跟查詢區間有交集 res=max(res,query(cl(id),l,mid,sl,sr)); } if(mid<sr){//右區間跟查詢區間有交集 res=max(res,query(cr(id),mid+1,r,sl,sr)); } return res; } ``` ---- ## 區間求總和 給一個長度為$n$的陣列$a$,有$q$個操作,分為以下2種: - $1$ $l$ $r$ 詢問$[l,r]$區間的總和 - $2$ $x$ $v$ 把$a_x$設為$v$ $1 \le n,q \le 2*10^5$ ---- 可以發現就只是區間求最大值換成區間求總和 可以建出區間求總和的線段樹 <center> <img src="https://hackmd.io/_uploads/r1wYqBf96.png" width="900px"> </center> ---- 不難發現對於一個大區間而言,大區間的總和為左右兩個小區間相加 <center> <img src="https://hackmd.io/_uploads/BJ5L-87q6.png" width="700px"> </center> 像是區間[3,4]的值等於[3,3]+[4,4] 區間[5,8]的值等於[5,6]+[7,8] ---- build函式會跟區間求最大值一模一樣,因為只有更新答案的pull函式會不一樣,以下是區間求總和的pull函式 ```cpp! void pull(int id){ seg[id]=seg[cl(id)]+seg[cr(id)]; } ``` ---- 先來講這題的區間查詢🐍 這裡查詢[4,7]的總和 <center> <img src="https://hackmd.io/_uploads/BJcwQLX5a.png" width="900px"> </center> ---- 先看[0,8]的左右兩個子區間有沒有跟[4,7]交集到 因為都有,所以先往左遞迴 <center> <img src="https://hackmd.io/_uploads/Skhjm8Qc6.png" width="900px"> </center> ---- 現在到了[0,4],只有右邊有跟[4,7]交集到,往右邊遞迴 <center> <img src="https://hackmd.io/_uploads/BJvzEUm5p.png" width="900px"> </center> ---- 目前為[3,4],只有右邊有跟[4,7]交集到,往右邊遞迴 <center> <img src="https://hackmd.io/_uploads/H1S8NU75T.png" width="900px"> </center> ---- 目前為[4,4],因為這個區間被包含在[4,7]裡面,回傳這個區間的答案 <center> <img src="https://hackmd.io/_uploads/ByNRV8Qcp.png" width="900px"> </center> ---- 回到[0,8],解決右邊的部分還沒解決的部分,所以現在在[5,8] 因為[5,8]的左右兩個子區間都有跟[4,7]交集到,先往左遞迴 <center> <img src="https://hackmd.io/_uploads/SJQWrIQqa.png" width="900px"> </center> ---- 因為[5,6]的被[4,7]包含,回傳這個區間的答案 <center> <img src="https://hackmd.io/_uploads/HJXtrLXqT.png" width="900px"> </center> ---- 回到[5,8]解決右邊還沒解決的部分,所以現在到[7,8] 因為[7,8]的左區間跟[4,7]交集,右邊沒有,所以往左遞迴 <center> <img src="https://hackmd.io/_uploads/B1EkIIX9T.png" width="900px"> </center> ---- 現在到[7,7],因為[7,7]在[4,7]內,所以回傳這個區間的答案 <center> <img src="https://hackmd.io/_uploads/B1aGIIX9a.png" width="900px"> </center> ---- 總共有[4,4]、[5,6]、[7,7]這些區間 <center> <img src="https://hackmd.io/_uploads/B1aGIIX9a.png" width="900px"> </center> ---- 區間查詢code be like: ```cpp! int query(int id,int l,int r,int sl,int sr){ if(sl<=l&&r<=sr){ return seg[id]; } int mid=(l+r)>>1,res=0; if(sl<=mid){ res+=query(cl(id),l,mid,sl,sr);//回傳值相加 } if(mid<sr){ res+=query(cr(id),mid+1,r,sl,sr);//回傳值相加 } return res; } ``` ---- 單點加值的話 這裡假設要在第三個單點加值7,也就是[2,2]這個區間 一樣先透過遞迴找到[2,2]這個區間 <center> <img src="https://hackmd.io/_uploads/Sy05D8mc6.png" width="900px"> </center> ---- 因為是加上7,所以[2,2]這個區間變成16 <center> <img src="https://hackmd.io/_uploads/SJvZOL7q6.png" width="900px"> </center> ---- 所經過的節點也要由下往上更新 <center> <img src="https://hackmd.io/_uploads/B12POU7ca.png" width="900px"> </center> ---- 所經過的節點也要由下往上更新 <center> <img src="https://hackmd.io/_uploads/rkVfKU756.png" width="900px"> </center> ---- 更新完畢 <center> <img src="https://hackmd.io/_uploads/ByZLFLXqp.png" width="900px"> </center> --- ## 休息一下,等等有一堆例題講解! --- ## 例題:[正負交替](https://codeforces.com/edu/course/2/lesson/4/4/practice/contest/274684/problem/A) 給一個長度為$n$的陣列$a$,有$q$個操作,分為以下2種: - $1$ $x$ $v$ 把$a_x$設為$v$ - $2$ $l$ $r$ 詢問$a_l-a_{l+1}+a_{l+2}...\pm a_{r}$的總和 ---- 觀察到每次詢問的正和負都是交替的 而$l$的位置固定為正 因此可以用$l$所在位置的奇偶性來建樹 ---- - 建偶數位為正值、奇數位為負值的樹 - 建偶數位為負值、奇數位為正值的樹 根據不同的$l$再去判斷要用哪顆線段樹去query就好了 ---- ## 例題:[區間不同數字數量](https://codeforces.com/edu/course/2/lesson/4/4/practice/contest/274684/problem/D) 給一個長度為$n$的陣列$a$,$q$筆操作,有以下兩種操作 - $1$ $l$ $r$ 詢問區間$[l,r]$內有幾種不同的數字 - $2$ $x$ $v$ 把$a_x$設為$v$ $1 \le n,q \le 10^5$ $1 \le a_i \le 40$ ---- $a_i$最多有四十種,對於每一種$a_i$開一棵線段樹 時間複雜度:$O(nlogn)$ 空間複雜度:40\*4\*100000\*4bytes ---- 或是可以開一顆線段樹,裡面存long long的數字 long long可以存 64個bit,每一種bit存不同數字 再用or去運算求答案 ---- ## 例題:[區間最大連續和](https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/problem/A) 給一個長度為$n$的陣列$a$,有$q$個操作,分為以下2種: - $1$ $l$ $r$ 詢問$[l,r]$的區間最大連續和 - $2$ $x$ $v$ 把$a_x$設為$v$ $1 \le n,q \le 2*10^5$ ---- 線段樹的核心觀念在於如何把小區間的答案合併到大區間 可以取下面兩塊小區間的答案轉移到大區間上 <center> <img src="https://hackmd.io/_uploads/HklaiFjYp.png" width="800px"> </center> ans是指每個區間的答案 ---- 如果大區間的最大連續和橫跨兩個區間並且為答案 <center> <img src="https://hackmd.io/_uploads/Hy4ITtsYT.png" width="900px"> </center> 需要下面兩塊的最大前綴和最大後綴相加 ---- 對於每一塊可以存當前總和、最大前綴、最大後綴和、當前區間內的區間連續最大和 <center> <img src="https://hackmd.io/_uploads/SJRjCYoKa.png" width="900px"> </center> ---- 把每個節點的資訊包成struct ```cpp! struct node{ int ans;//這個區間的答案 int sum;//這個區間的總和 int suf;//suffix 最大後綴 int pre;//prefix 最大前綴 }seg[4*N]; ``` ---- 總和: <center> <img src="https://hackmd.io/_uploads/ByImWqiYT.png" width="800px"> </center> $seg[id].sum=seg[cl(id)].sum+seg[cr(id)].sum$ ---- 最大前綴: <center> <img src="https://hackmd.io/_uploads/r1e4Q9sKT.png" width="800px"> </center> $$ seg[id].pre=max \begin{cases} seg[cl(id)].pre \\ seg[cl(id)].sum+seg[cr(id)].pre \end{cases} $$ ---- 最大後綴: <center> <img src="https://hackmd.io/_uploads/B1bNNqoKT.png" width="800px"> </center> $$ seg[id].suf=max \begin{cases} seg[cr(id)].suf \\ seg[cr(id)].sum+seg[cl(id)].suf \end{cases} $$ ---- 區間連續最大和: <center> <img src="https://hackmd.io/_uploads/B1vMS9iYT.png" width="700px"> </center> $$ seg[id].ans=max \begin{cases} seg[cl(id)].ans \\ seg[cr(id)].ans \\ seg[cl(id)].suf+seg[cr(id)].pre \end{cases} $$ ---- 因此會這樣更新: ```cpp! struct node{ int sum,pre,suf,ans;//總和、最大前綴、最大後綴、當前區間答案 }seg[4*N]; void pull(int id){ int l=cl(id),r=cr(id);//左右兩個子區間的index seg[id].sum=seg[l].sum+seg[r].sum; seg[id].pre=max(seg[l].pre,seg[l].sum+seg[r].pre); seg[id].suf=max(seg[r].suf,seg[r].sum+seg[l].suf); seg[id].ans=max({seg[l].ans,seg[r].ans,seg[l].suf+seg[r].pre}); } ``` --- ## 線段樹上二分搜 由於線段樹上每個大區間都會二分成兩個小區間 因此可以做一些二分搜之類的操作 ---- ## 例題:[第k個1](https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/problem/B) 長度為$n$的陣列$a$內只有0和1兩種數字,$q$筆操作 分為以下兩種: - $1$ $k$ 詢問陣列從左往右數來第$k$個1在哪個index - $2$ $x$ 把$a_x$的1變0或是0變1 $1 \le n,q \le 10^5$ ---- 假設陣列為a=[0,1,1,1,0,1,1,0] 可以以建區間總和的線段樹來做 這裡假設要查第四個1在哪裡 <center> <img src="https://hackmd.io/_uploads/B13x5CiF6.png" width="700px"> </center> ---- 左區間有三個1 右區間兩個1 往右邊遞迴找右邊的第一個1 <center> <img src="https://hackmd.io/_uploads/Byk6qCiF6.png" width="700px"> </center> ---- 左區間有一個1 右區間一個1 往左邊遞迴找左邊的第一個1 <center> <img src="https://hackmd.io/_uploads/Bk--n0sK6.png" width="700px"> </center> ---- 左區間有零個1 右區間一個1 往右邊遞迴找右邊的第一個1 <center> <img src="https://hackmd.io/_uploads/B1aBhAiK6.png" width="700px"> </center> ---- 找到了,回傳這個區間的$l$或$r$ <center> <img src="https://hackmd.io/_uploads/rkBu3CiKa.png" width="700px"> </center> ---- ## 例題:[至少大於K的第一個元素](https://codeforces.com/edu/course/2/lesson/4/2/practice/contest/273278/problem/C) 給一個長度為$n$的陣列$a$,$q$筆操作,有以下兩種操作 - $1$ $k$ 詢問陣列從左往右數來第一個大於$k$的數字的index - $2$ $x$ $v$ 把$a_x$設為$v$ $1 \le n,q \le 10^5$ ---- 跟上一題概念一樣只是換成區間求最大的線段樹 ---- 能往左區間走就往左,否則往右 直到走到最下面,並回傳這個位置的$l$或$r$ <center> <img src="https://hackmd.io/_uploads/BJagik3tp.png" width="900px"> </center> 上圖為$k=8$的例子 --- 來實作吧: [homework link](https://vjudge.net/contest/603687)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully