原題是sdoi2011染色
反正鏈剖都長得差不多不一樣的就是線段樹根據題自己在查詢和修改裡改一改就好了
跟著黃學長學的倍增記錄祖先的寫法,和網上不太一樣求不噴
注釋棒棒噠
**又長跑的也不快我也是醉了
注釋**根據題目不同自己修改
#include
#include
#include
#include
#include
#define maxint 0x7fffffff
#define maxn 100010
#define lchild rt<<1,l,mid
#define rchild rt<<1|1,mid+1,r
#define ln rt<<1
#define rn rt<<1|1
using
namespace
std;
int n,m;
int top,tp;
int co[maxn];
int a,b,color;
int deep[maxn],size[maxn],chain[maxn],fa[maxn][18],num[maxn];
//deep 深度,size 子樹大小,chain 接的鏈,fa 父親節點,num 點的編號
bool vis[maxn];//節點是否已經訪問過
char ch[2];
struct seg
tree[maxn*4];
struct edge
e[maxn*2],*prev[maxn];
void insert(int u,int v)
void dfs1(int x)//第一遍dfs處理子樹大小/祖先關係/深度
for (edge *i=prev[x];i;i=i->next)
}void dfs2(int x,int last)//接鏈上編號.last為之前的鏈
/*void push_up(int rt)
*//*void push_down(int rt)
*/void build(int rt=1,int l=1,int r=n)
int lca(int a,int b)//最近公共祖先.將鏈提到最近公共祖先上
if (a==b) return a;
else
return fa[a][0];
}void modify(int rt,int l,int r,int col)//修改區間顏色
int mid=(l+r)>>1;
if (r<=mid) modify(ln,l,r,col);
else
if (l>mid) modify(rn,l,r,col);
else
push_up(rt);
}void modify(int a,int b,int col)//修改兩點間路徑顏色
modify(1,num[b],num[a],col);//在把鏈上提之後a在b的左側
//(差不多就是這個意思自己懂就行...)
}int query(int rt,int l,int r)//查詢區間顏色段數目
}int pointcolor(int rt,int x)//查詢某個點的顏色 (可以看做是查詢權值)
int query(int a,int b)//查詢兩點間路徑顏色段數目
ret+=query(1,num[b],num[a]);
return ret;
}int main()
dfs1(1);
dfs2(1,1);
build();
for (int i=1;i<=n;i++)
modify(1,num[i],num[i],co[i]);
for (int i=1;i<=m;i++)
else
}}
樹鏈剖分 模板
class match node a n struct no no aa n 4 void init void addpage int x,int y void dfs int s,int faa,int h 根節點,父節點和深度的 if max 0 son s sign void dfs2 int...
模板 樹鏈剖分
define maxn 50010 define l u u 1 define r u u 1 1 寫在類裡面爆棧 int n,m,q int tim 時間戳 int num maxn 樹上每個節點的初始值 int siz maxn siz u 表示以u為根的子樹的節點數 int top maxn ...
樹鏈剖分模板
點權模板 1 m a b c將節點a到節點b路徑上所有點都染成顏色c 2 q a b詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 const int n 100100 struct edge g n 2 int cnt,head...