标签:hang name 结果 swa nod 操作 例题 clu count
重儿子:节点u所有的儿子中,siz最大的儿子;
轻儿子:节点u所有的非重儿子的儿子;
重链:所有连续重儿子连接成的链;
轻链(轻边):由节点u跟轻儿子连接的边,最多包含两个定点。
所有的重链个数不超过.
所有的轻边的个数不超过;
轻边的size*2<SIZE;
val[u] 节点u的价值
tid[u] 节点u的新编号,用于维护线段树
valt[u] 节点u的新编号对应的价值,用于维护线段树
size[u] 以u为根的子树的节点数; 用于区分重儿子和轻儿子。
dep[u] 节点v的深度,根节点的深度为1或0;
top[u] 节点u所在链的顶端节点,(u,v)如果为重链,top[u]==top[v],轻链或者轻链重链的结合,top[u]!=top[v].
fa[u] 表示u节点的额父亲节点
邻接表存树
DFS1,维护出fa[],dep[]和siz[]
DFS2,优先访问重儿子,维护出tid[],valt[],top[]
用tid[]和valt[]建立线段树。
修改,修改u的tid[u]在线段树上的值即可。
查询,两部查询,把查询的链分成重链和轻链查询。如果是复合链,优先查询dep[top[u]]深度深的一端。防止查询越界。
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II。QMAX u v: 询问从点u到点v的路径上的节点的最大权值。 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和。注意:从点u到点v的路径上的节点包括u和v本身。
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e4 + 15;
int N, Q, u, v;
//-----------------------邻接表
struct node
{
int id, next;
} E[maxn << 1]; //双向边
int head[maxn], num;
void init()
{
memset(head, -1, sizeof(head));
num = 0;
}
void adde(int u, int v)
{
E[num].id = v;
E[num].next = head[u];
head[u] = num++;
}
//--------------------------------DFS1/2
int val[maxn], valt[maxn], tid[maxn], siz[maxn], top[maxn],
dep[maxn], fa[maxn];
int clk;
void DFS1(int u, int p)
{
dep[u] = dep[p] + 1;
fa[u] = p;
siz[u] = 1;
for(int k = head[u]; k != -1; k = E[k].next)
{
int id = E[k].id;
if(id == p) continue;
DFS1(id, u);
siz[u] += siz[id];
}
}
void DFS2(int u, int p)
{
tid[u] = ++clk;
valt[clk] = val[u];
int son = -1;
for(int k = head[u]; k != -1; k = E[k].next)
{
int id = E[k].id;
if(id == p)continue;
if(son == -1 || siz[id] > siz[son]) son = id;
}
if(son != -1)
{
top[son] = top[u];
DFS2(son, u);
}
for(int k = head[u]; k != -1; k = E[k].next)
{
int id = E[k].id;
if(id == p || id == son)continue;
top[id] = id;
DFS2(id, u);
}
}
//--------------------------------线段树
int mx[maxn*4], sum[maxn*4];
void build(int id, int l, int r)
{
if(l == r) mx[id] = sum[id] = valt[l];
else
{
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
mx[id] = max(mx[id << 1], mx[id << 1 | 1]);
sum[id] = sum[id << 1] + sum[id << 1 | 1];
}
}
void update(int id, int l, int r, int u, int vual)
{
if(l == r) mx[id] = sum[id] = vual;
else
{
int mid = (l + r) >> 1;
if(u <= mid) update(id << 1, l, mid, u, vual);
else update(id << 1 | 1, mid + 1, r, u, vual);
mx[id] = max(mx[id << 1], mx[id << 1 | 1]);
sum[id] = sum[id << 1] + sum[id << 1 | 1];
}
}
int QMax(int id, int L, int R, int l, int r)
{
if(R <= r && L >= l) return mx[id];
else
{
int mid = (L + R) >> 1;
int ret = -INT_MAX;
if(l <= mid)ret = max(ret, QMax(id << 1, L, mid, l, r));
if(r >= mid + 1) ret = max(ret, QMax(id << 1 | 1, mid + 1, R, l, r));
return ret;
}
}
int QMax(int u, int v)
{
int ret = -INT_MAX;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ret = max(ret, QMax(1, 1, N, tid[top[u]], tid[u]));
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
ret = max(ret, QMax(1, 1, N, tid[v], tid[u]));
return ret;
}
int Qsum(int id, int L, int R, int l, int r)
{
if(R <= r && L >= l) return sum[id];
else
{
int mid = (L + R) >> 1;
int ret = 0;
if(l <= mid)ret += Qsum(id << 1, L, mid, l, r);
if(r >= mid + 1) ret += Qsum(id << 1 | 1, mid + 1, R, l, r);
return ret;
}
}
int Qsum(int u, int v)
{
int ret = 0;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
{
ret += Qsum(1, 1, N, tid[top[u]], tid[u]);
u = fa[top[u]];
}
}
if(dep[u] < dep[v]) swap(u, v);
ret += Qsum(1, 1, N, tid[v], tid[u]);
return ret;
}
//--------------------------------主函数
int main ()
{
init();
scanf("%d",&N);
for(int i = 1; i < N; i++)
{
scanf("%d %d", &u, &v);
adde(u, v);
adde(v, u);
}
for(int i = 1; i <= N; i++)
scanf("%d", &val[i]);
DFS1(1, 0);
top[1] = 1;
DFS2(1, 0);
build(1, 1, N);
char s[10];
scanf("%d", &Q);
for(int i = 1; i <= Q; i++)
{
scanf("%s%d%d", s, &u, &v);
if(!strcmp(s, "QMAX"))
printf("%d\n", QMax(u, v));
else if(!strcmp(s, "QSUM"))
printf("%d\n",Qsum(u, v));
else
{
update(1, 1, N, tid[u], v);
}
}
return 0;
}
标签:hang name 结果 swa nod 操作 例题 clu count
原文地址:http://www.cnblogs.com/pealicx/p/7622499.html