题意:给你一棵树,每次一个操作,修改书上最多不超过1000个点的值,然后询问u到v路径上的权值和。
分析:树链剖分,后边单点修改区间查询可以用树状数组。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define N 500005
using namespace std;
typedef long long ll;
ll val[N],f[4*N];
int dep[N],siz[N],fa[N],id[N],son[N],top[N],fid[N];
int T,q,n,num;
vector <int> G[N];
struct Segtree
{
int l,r;
ll val;
} tree[4*N];
void dfs1(int u,int f,int d)
{
dep[u] = d;
siz[u] = 1;
son[u] = 0;
fa[u] = f;
for(int v : G[u])
if(v != f)
{
dfs1(v,u,d+1);
siz[u] += siz[v];
if(siz[son[u]] < siz[v]) son[u] = v;
}
}
int lowbit(int x)
{
return (x & (-x));
}
void Insert(int x,ll val)
{
while(x <= n)
{
f[x] += val;
x += lowbit(x);
}
}
ll Find(int x)
{
ll ans = 0;
while(x)
{
ans += f[x];
x -= lowbit(x);
}
return ans;
}
ll query(int x,int y)
{
return (Find(y) - Find(x-1));
}
void dfs2(int u,int tp)
{
top[u] = tp;
id[u] = ++num;
fid[id[u]] = u;
if(son[u]) dfs2(son[u],tp);
for(int v : G[u])
if(v != fa[u] && v != son[u]) dfs2(v,v);
}
ll Yougth(int u,int v)
{
int tp1 = top[u],tp2 = top[v];
ll ans = 0;
while(tp1 != tp2)
{
if(dep[tp1] < dep[tp2])
{
swap(tp1,tp2);
swap(u,v);
}
ans += query(id[tp1],id[u]);
u = fa[tp1];
tp1 = top[u];
}
if(dep[u] > dep[v]) swap(u,v);
ans += query(id[u],id[v]);
return ans;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i < n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
G[x].push_back(y);
G[y].push_back(x);
}
num = 0;
dfs1(1,0,1);
dfs2(1,1);
for(int i = 1;i <= n;i++)
{
scanf("%I64d",&val[i]);
Insert(id[i],val[i]);
}
scanf("%d",&q);
for(int i = 1;i <= q;i++)
{
int K,u,v;
ll x1,y1,A,B,C,D;
scanf("%d%I64d%I64d%I64d%I64d%I64d%I64d%d%d",&K,&x1,&y1,&A,&B,&C,&D,&u,&v);
Insert(id[x1+1],y1);
for(int j = 1;j < K;j++)
{
x1 = (A*x1 + B),y1 = (C*y1 + D);
if(x1 >= n) x1 = x1 % n;
if(y1 >= MOD) y1 = y1 % MOD;
Insert(id[x1+1],y1);
}
u++,v++;
printf("%I64d\n",Yougth(u,v));
}
return 0;
}