給出乙個 \(n\) 個節點的有根樹(編號為 \(0\) 到 \(n-1\),根節點為 \(0\))。乙個點的深度定義為這個節點到根的距離 \(+1\) 。
設 \(dep[i]\) 表示點 \(i\) 的深度,\(lca(i,j)\) 表示 \(i\) 與 \(j\) 的最近公共祖先。
有 \(q\) 次詢問,每次詢問給出 \(l,r,z\),求 \(∑_^dep[lca(i,z)]\) 。
(即,求在 \([l,r]\) 區間內的每個節點i與z的最近公共祖先的深度之和)
第一行 \(2\) 個整數 \(n,q\)。
接下來 \(n-1\) 行,分別表示點 \(1\) 到點 \(n-1\) 的父節點編號。
接下來 \(q\) 行,每行 \(3\) 個整數 \(l,r,z\)。
輸出 \(q\) 行,每行表示乙個詢問的答案。每個答案對 \(201314\) 取模輸出
樣例輸入
5 200
111 4 3
1 4 2
樣例輸出8
5
共 \(10\) 組資料,\(n\) 與 \(q\) 的規模分別為 \(1000,2000,3000,4000,5000,10000,20000,30000,40000,50000\)。
#include#include#include#include#include#define r register
#define n 200010
#define int long long
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}const int mod = 201314;
int n,q,dep[n],f[n],siz[n],son[n],dfn[n],cnt,top[n],head[n],ans[n];
int tr[n<<2],tag[n<<2];
struct edgee[n<<1];
struct problem
problem(int _pos,int _z,int _id,int _flag)
bool operator <(const problem &a)const
}ask[n<<1];
int len;
void addedge(int u,int v)
void dfs(int u,int fa)
}void dfs2(int u,int tp)
}#define ls rt<<1
#define rs rt<<1|1
inline void pushdown(int rt,int l,int r)
}void update(int rt,int l,int r,int s,int t)
pushdown(rt,l,r);
int mid = (l+r)>>1;
if(s<=mid)update(ls,l,mid,s,t);
if(t>mid)update(rs,mid+1,r,s,t);
tr[rt] = tr[ls]+tr[rs];
}int query(int rt,int l,int r,int s,int t)
void modify(int u,int v)
int getsum(int u,int v)
signed main()
dfs(1,0);
dfs2(1,0);
int tot = 0;
for(int i = 1;i <= q;i++)
sort(ask,ask+tot);
int cur = 1;
for(int i = 0;i < tot;i++)
for(int i = 1;i <= q;i++)
return 0;
}
poj 3237 樹鏈剖分 線段樹
題意 給一棵樹,三種操作。將第i條邊的權值改為v,將a到b的路徑上的邊的權值全部取反,求a到b路徑上邊的權值的最大值。思路 明顯的樹鏈剖分,加上線段樹的操作。因為有取反的操作所以每個區間要記錄最大值和最小值。查詢兩點間的路徑時,用求公共祖先的方式去求。include include includec...
hdu 3966(樹鏈剖分 線段樹)
題意 給出一棵樹,每個節點有一些敵人,有三種操作,i x,y,路徑上的所有點的人數 w。d x,y,路徑上的所有點的人數 w。q 節點x的人數。pragma comment linker,stack 1024000000,1024000000 include include include usin...
poj 3237 樹鏈剖分 線段樹
題意就是給你一棵樹,每條邊上都有權值,有三種操作,把某條邊的權值變成v,把點a到點b之間的路徑上的邊的權值都乘上 1,求a到b的路徑上的最大值。其實這題的線段樹要比樹鏈剖分難寫,首先,因為有乘 1的操作,所以不光要維護最大值,還要維護最小值,這樣在乘 1後,最大值就可以直接根據最小值得到,當然,延遲...