题意:给出一棵树,每次可以使任意两点间的路径的权值加1,最后求出每条边的权值
题解:可以作为基于边权的树链剖分的模板,有个技巧是用eg数组来将边的序号和点关联起来
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m;
int cnt, head[100010];
int eg[100010][2];
int e[100010];
int fa[100010];
int siz[100010];
int dep[100010];
int son[100010];
int top[100010];
int tid[100010], rnk[100010];
struct Edge{
int v, next;
}edge[2*100010];
struct node{
int l, r;
int sum;
int tag;
}s[4*100010];
void push(int k){
if(s[k].tag){
s[2*k].tag += s[k].tag;
s[2*k+1].tag += s[k].tag;
s[k].sum = (s[2*k].r-s[2*k].l+1)*s[2*k].tag + (s[2*k+1].r-s[2*k+1].l+1)*s[2*k+1].tag;
s[k].tag = 0;
}
}
void build(int l, int r, int k){
s[k].l = l; s[k].r = r; s[k].tag = 0; s[k].sum = 0;
if(l == r){
return;
}
int mid = (l+r)>>1;
build(l, mid, 2*k);
build(mid+1, r, 2*k+1);
}
void update(int l, int r, int k){
if(s[k].l == l && s[k].r == r){
s[k].tag += 1;
return;
}
push(k);
int mid = (s[k].l+s[k].r)>>1;
if(r<=mid) update(l, r, 2*k);
else if(l>mid) update(l, r, 2*k+1);
else{
update(l, mid, 2*k);
update(mid+1, r, 2*k+1);
}
}
int query(int x, int k){
if(s[k].l == x && s[k].r == x){
return s[k].sum+(s[k].r-s[k].l+1)*s[k].tag;
}
push(k);
int mid = (s[k].l+s[k].r)>>1;
if(x<=mid) return query(x, 2*k);
else return query(x, 2*k+1);
}
void init(){
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
cnt = 0;
}
void addedge(int u, int v){
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs1(int u, int father, int depth){
dep[u] = depth;
fa[u] = father;
siz[u] = 1;
for(int i = head[u]; i!=-1; i = edge[i].next){
int v = edge[i].v;
if(v!=fa[u]){
dfs1(v, u, depth+1);
siz[u] += siz[v];
if(son[u]!=-1 || siz[v]>siz[son[u]]){
son[u] = v;
}
}
}
}
void dfs2(int u, int t){
top[u] = t;
tid[u] = cnt;
rnk[cnt] = u;
cnt++;
if(son[u] == -1){
return;
}
dfs2(son[u], t);
for(int i = head[u]; i!=-1; i = edge[i].next){
int v = edge[i].v;
if(v!=son[u] && v!=fa[u]){
dfs2(v, v);
}
}
}
void tree_update(int u, int v){
int f1 = top[u];
int f2 = top[v];
while(f1!=f2){
if(dep[f1]<dep[f2]){
swap(f1, f2);
swap(u, v);
}
update(tid[f1], tid[u], 1);
u = fa[f1]; f1 = top[u];
}
if(u == v) return;
if(dep[u]>dep[v]) swap(u, v);
update(tid[son[u]], tid[v], 1);
}
int main(){
init();
scanf("%d", &n);
for(int i = 1; i<=n-1; i++){
scanf("%d %d", &eg[i][0], &eg[i][1]);
addedge(eg[i][0], eg[i][1]);
addedge(eg[i][1], eg[i][0]);
}
for(int i = 1; i<=n-1; i++){
if(dep[eg[i][0]] > dep[eg[i][1]]){
swap(eg[i][0], eg[i][1]);
}
}
dfs1(1, 0, 1);
cnt = 0;
dfs2(1, 1);
build(0, cnt-1, 1);
/*for(int i = 1; i<=5; i++){
cout<<"i: "<<i<<" tid[i]: "<<tid[i]<<" siz[i]: "<<siz[i]<<" dep[i]: "<<dep[i]<<" fa[i]: "<<fa[i];
cout<<" son[i] "<<son[i]<<" top[i]: "<<top[i]<<endl;
}*/
scanf("%d", &m);
while(m--){
int u, v;
scanf("%d %d", &u, &v);
tree_update(u, v);
}
for(int i = 1; i<=n-1; i++){
if(dep[eg[i][0]] > dep[eg[i][1]]){
swap(eg[i][0], eg[i][1]);
}
}
for(int i = 1; i<=n-1; i++){
printf("%d", query(tid[eg[i][1]], 1));
if(i!=n-1) printf(" ");
else printf("\n");
}
return 0;
}