hdu 3966(樹鏈剖分 線段樹)

2021-06-28 06:13:24 字數 1394 閱讀 1274

題意:給出一棵樹,每個節點有一些敵人,有三種操作,i:x,y,路徑上的所有點的人數+w。d:

x,y,路徑上的所有點的人數-w。q:節點x的人數。

#pragma comment(linker, "/stack:1024000000,1024000000")

#include#include#include using namespace std;

const int n=100005;

int son[n];//重兒子;

int sz[n];//以該節點為根的子結點數(包括自己)

int dep[n];//該節點到根的距離

int top[n];//該節點所在重鏈最頂端節點

int father[n];//每個節點的父節點

int head[n];//用於構造鄰接表

int ti[n];//該點對映到線段樹中的位置

int num,idx,a[n];

struct edge

e[n];

void addedge(int x,int y)//構造鄰接表儲存邊

//****************樹鏈剖分****************

void find_son(int u)//第一次dfs求出father·dep·size·son陣列

}void find_ti(int u,int fa)//第二次dfs求top和ti陣列

}//***************線段樹****************

struct tree

t[n];

void buildtree(int l,int r,int id)//建線段樹

void insert(int l,int r,int id,int w)//為線段樹儲存的l~r區間增加w

int mid=(t[id].l+t[id].r)>>1;

int li=id<<1;

int ri=li+1;

if(mid>=r) insert(l,r,li,w);

else if(mid>1,li=id<<1,ri=li+1;

if(mid>=i)return findw(i,li,w+t[id].ct);

else return findw(i,ri,w+t[id].ct);

}void lca(int x,int y,int w)//為原題要求x~y路徑上各點增加w

int main()

father[1]=sz[0]=0;dep[1]=idx=1;

find_son(1);

find_ti(1,1);

buildtree(1,n,1);

while(q--)

else}}

return 0;

}

hdu 3966 樹鏈剖分 線段樹

題意 給出一棵樹,每個節點有一些敵人,有三種操作,i x,y,路徑上的所有點的人數 w。d x,y,路徑上的所有點的人數 w。q 節點x的人數。思路 如果是線性的線段樹可以做,所以要樹鏈剖分,剖分後的每條鏈是線性的,更改區間時用找公共祖先的方式,將兩點找到同一條鏈上,同一條鏈上的兩點間可以直接線段樹...

HDU3966 樹鏈剖分

題目 aragorn s story 題意 給一棵樹,並給定各個點權的值,然後有3種操作 i c1 c2 k 把c1與c2的路徑上的所有點權值加上k d c1 c2 k 把c1與c2的路徑上的所有點權值減去k q c 查詢節點編號為c的權值 分析 典型的樹鏈剖分題目,先進行剖分,然後用線段樹去維護即...

hdu3966 樹鏈剖分

近期在強化知識點深度。發現樹鏈剖分不是非常會寫了。回想一下改動操作 若兩個點在同一條鏈上,則直接改動這段區間。若不在同一條鏈上,改動深度較大的點到其鏈頂端的區間,同一時候將這個點變為他所在鏈頂端的父親,迴圈操作直到這兩個點在同一條鏈上。就能夠用上一種方法了。沒實用lca寫是由於曾經被坑過,不但沒有這...