題意:有一棵樹,每個節點有權值。
我們現在有三個操作:
1、改變某點的權值。
2、給出兩個點,求這兩個點之間的路徑上所有點的權值之和。
3、給出兩個點,求這兩個點之間的路徑上所有點的最大權值。
乙個裸的樹剖,刷了兩三天樹剖的題了,感覺現在已經把樹剖理解的差不多了,具體操作現在已經可以很快在腦海中模擬出來了。
#include #include #include #include #include #include using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 3e4+10;
int value[maxn],head[maxn];
int n,q,edge_cnt,tot;
struct edgeedge[maxn<<1];
void add(int u,int v)
int size[maxn],son[maxn],fa[maxn],deep[maxn];
void dfs1(int now,int father,int deep) }}
int id[maxn],rank[maxn],top[maxn];
void dfs2(int now,int top)
}#define mid int mid = (l+r)>>1
#define mid int mid = (tree[now].l+tree[now].r)>>1
struct info;
info(int l1,int r1,int val_max1,int val_sum1)
void init(int val)
void clear()
};info operator + (info a,info b)
struct sgt
mid;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tree[now] = tree[now<<1]+tree[now<<1|1];
} void update(int now,int idx,int val)
mid;
if(idx <= mid)
update(now<<1,idx,val);
else
update(now<<1|1,idx,val);
tree[now] = tree[now<<1]+tree[now<<1|1];
} info query(int now,int l,int r)
};sgt sgt;
info work(int u,int v)
u = u + sgt.query(1,id[tpu],id[u]);
u = fa[tpu];
tpu = top[u];
} if(deep[u] > deep[v])
return u+sgt.query(1,id[u],id[v])+v;
}int main()
for(int i = 1; i <= n; i++)
scanf("%d",&value[i]);
dfs1(1,0,0);
dfs2(1,1);
sgt.build(1,1,n);
scanf("%d",&q);
char op[10];
while(q--)
} }return 0;}/*
41 2
2 34 1
4 2 1 3
12qmax 3 4
qmax 3 3
qmax 3 2
qmax 2 3
qsum 3 4
qsum 2 1
change 1 5
qmax 3 4
change 3 6
qmax 3 4
qmax 2 4
qsum 3 4
*/
HYSBZ 1036 樹的統計Count
一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成 一些操作 i.change u t 把結點u的權值改為t ii.qmax u v 詢問從點u到點v的路徑上的節點的最大權值 i ii.qsum u v 詢問從點u到點v的路徑上的節點的權值和 注意 ...
HYSBZ 1036樹鏈剖分
一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成 一些操作 i.change u t 把結點u的權值改為t ii.qmax u v 詢問從點u到點v的路徑上的節點的最大權值 i ii.qsum u v 詢問從點u到點v的路徑上的節點的權值和 注意 ...
bzoj1036 樹的統計
一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成一些操作 i.change u t 把結點u的權值改為t ii.qmax u v 詢問從點u到點v的路徑上的節點的最大權值 iii.qsum u v 詢問從點u到點v的路徑上的節點的權值和 注意 從點...