题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5405

题意: 给你一棵n个节点的树,有点权。

         要求支持两种操作:

    操作1:更改某个节点的权值。

    操作2:给定u,v, 求 Σw[i][j]   i , j 为任意两点且i到j的路径与u到v的路径相交。

解法:

  这是一个大树剖题。 

  容易发现对于一个询问,答案为总点权和的平方 减去 去掉u--v这条链后各个子树的点权和的平方的和。

  开两棵线段树,tag1记录点权和,tag2记录某点的所有轻链子树的点权和的平方的和。

  每次沿着重链往上走时,直接加上这条重链的所有点的tag2和,若有重儿子则直接用tag1计算。由于该条重链必定为其父亲的轻链,故为防止计算重复,还需减去该重链所有点的tag1平方和。

  最后爬到同一颗重链后,还需计算重链上方所有点的贡献。

//HDU 5405

//答案为总点权和的平方 减去 去掉u--v这条链后各个子树的点权和的平方的和。
//T1记录点权和,T2记录某点的所有轻链子树的点权和的平方的和
//每次沿着重链往上走时,直接加上这条重链的所有点的tag2和,若有重儿子则直接用tag1计算。
//由于该条重链必定为其父亲的轻链,故为防止计算重复,还需减去该重链所有点的tag1平方和。
//最后爬到同一颗重链后,还需计算重链上方所有点的贡献。 #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const int mod = 1e9+7;
struct Tree{
LL sum[maxn<<2];
void build(){
memset(sum,0,sizeof(sum));
}
void pushup(int rt){
sum[rt] = (sum[rt<<1]+sum[rt<<1|1])%mod;
}
void update(int pos, LL v, int l, int r, int rt){
if(l == r){
sum[rt] += v;
sum[rt] %= mod;
return;
}
int mid = (l+r)>>1;
if(pos <= mid) update(pos, v, l, mid, rt<<1);
else update(pos, v, mid+1, r, rt<<1|1);
pushup(rt);
}
LL query(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R){
return sum[rt];
}
int mid = (l+r)/2;
if(R<=mid) return query(L,R,l,mid,rt<<1)%mod;
else if(L>mid) return query(L,R,mid+1,r,rt<<1|1)%mod;
else return (query(L,mid,l,mid,rt<<1)+query(mid+1,R,mid+1,r,rt<<1|1))%mod;
}
}T1, T2;
int head[maxn],n, m, edgecnt, dfsclk;
struct edge{
int to,next;
}E[maxn*2];
int sz[maxn], top[maxn], son[maxn], dep[maxn];
int fa[maxn], tid[maxn], val[maxn];
void init(){
edgecnt = 0;
dfsclk = 0;
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
}
void addedge(int u, int v){
E[edgecnt].to = v, E[edgecnt].next = head[u], head[u] = edgecnt++;
}
void dfs1(int u, int father, int d){
dep[u] = d;
fa[u] = father;
sz[u] = 1;
for(int i = head[u]; ~i; i=E[i].next){
int v = E[i].to;
if(v == father) continue;
dfs1(v, u, d+1);
sz[u] += sz[v];
if(son[u] == -1 || sz[v]>sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp)
{
top[u] = tp;
tid[u] = ++dfsclk;
if(son[u] == -1) return;
dfs2(son[u], tp);
for(int i = head[u]; ~i; i=E[i].next){
int v = E[i].to;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
inline LL sqr(int x){
return (LL)x*x;
}
void update(int x, int v){
int u = top[x];
while(fa[u]){
LL sum = T1.query(tid[u], tid[u]+sz[u]-1, 1, n, 1);
T2.update(tid[fa[u]], ((sqr(val[x]-v)%mod)%mod-(LL)sum*2*(val[x]-v)%mod)%mod, 1, n, 1);
u = top[fa[u]];
}
T1.update(tid[x], v-val[x], 1, n, 1);
val[x] = v;
}
LL query(int x, int y){
LL ret = 0;
while(top[x] != top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret += T2.query(tid[top[x]], tid[x], 1, n, 1);
ret %= mod;
if(son[x]!=-1){
LL sum = T1.query(tid[son[x]], tid[son[x]]+sz[son[x]]-1, 1, n, 1);
ret = ret + sum*sum%mod;
ret %= mod;
}
LL sum = T1.query(tid[top[x]], tid[top[x]]+sz[top[x]]-1, 1, n, 1);
ret = (ret - sum*sum%mod + mod)%mod;
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ret += T2.query(tid[x], tid[y], 1, n, 1);
ret %= mod;
if(son[y]!=-1){
LL sum = T1.query(tid[son[y]], tid[son[y]]+sz[son[y]]-1, 1, n, 1);
ret = (ret + sum*sum%mod)%mod;
}
if(fa[x]){
LL sum = T1.query(1, n, 1, n, 1) - T1.query(tid[x], tid[x]+sz[x]-1, 1, n, 1);
ret = (ret+sum*sum%mod)%mod;
}
return ret;
}
int main()
{
while(~scanf("%d %d", &n,&m))
{
init();
T1.build();
T2.build();
for(int i=1; i<=n; i++) scanf("%d", &val[i]);
for(int i=1; i<n; i++){
int u, v;
scanf("%d %d", &u,&v);
addedge(u, v);
addedge(v, u);
}
dfs1(1, 0, 0);
dfs2(1, 1);
for(int i=1; i<=n; i++){
int x = val[i];
val[i] = 0;
update(i, x);
}
while(m--)
{
int op, x, y;
scanf("%d %d %d", &op,&x,&y);
if(op == 1){
update(x, y);
}
else{
LL sum = T1.query(tid[1], tid[1]+sz[1]-1, 1, n, 1);
sum = sum*sum;
sum = sum-query(x, y);
sum = sum%mod;
if(sum<0) sum+=mod;
printf("%lld\n", sum);
}
}
}
return 0;
}

2015多校第9场 HDU 5405 Sometimes Naive 树链剖分的更多相关文章

  1. HDU 5405 Sometimes Naive 树链剖分+bit*****

    Sometimes Naive Problem Description   Rhason Cheung had a naive problem, and asked Teacher Mai for h ...

  2. HDU 5029 Relief grain --树链剖分第一题

    题意:给一棵树,每次给两个节点间的所有节点发放第k种东西,问最后每个节点拿到的最多的东西是哪种. 解法:解决树的路径上的修改查询问题一般用到的是树链剖分+线段树,以前不会写,后来学了一下树链剖分,感觉 ...

  3. hdu 5029 Relief grain(树链剖分+线段树)

    题目链接:hdu 5029 Relief grain 题目大意:给定一棵树,然后每次操作在uv路径上为每一个节点加入一个数w,最后输出每一个节点个数最多的那个数. 解题思路:由于是在树的路径上做操作, ...

  4. HDU 5029 Relief grain 树链剖分打标记 线段树区间最大值

    Relief grain Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  5. HDU 4366 Successor(树链剖分+zkw线段树+扫描线)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...

  6. HDU 5044 Tree(树链剖分)

    HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai+Online&source=1&s ...

  7. 2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5354 题意:求删去每个点后图是否存在奇环(n,m<=1e5) 解法:很经典的套路,和这题一样:h ...

  8. 2015多校第6场 HDU 5361 并查集,最短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5361 题意:有n个点1-n, 每个点到相邻点的距离是1,然后每个点可以通过花费c[i]的钱从i点走到距 ...

  9. 2015多校第6场 HDU 5355 Cake 贪心,暴力DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题意:给你n个尺寸大小分别为1,2,3,…,n的蛋糕,要求你分成m份,要求每份中所有蛋糕的大小之 ...

随机推荐

  1. 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询

    题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...

  2. 在git 服务器挂载、创建新的项目、克隆新的项目

     流程,服务器创建项目名-->客户端克隆-->客户端提交并且推送-->完成   详细步骤   1.在git服务器路径文件夹下创建空文件夹,名字为新的项目名,如在  F:\git   ...

  3. 【题解】51nod1327 棋盘游戏

    那天和机房的同学们一起想了很久,然而并没有做出来……今天看了题解,的确比较巧妙,不过细细想来其实规律还是比较明显,在这里记录一下~ 当天自己做的时候,主要想到的是两点 : 1.按列dp 2.对行进行排 ...

  4. 【刷题】洛谷 P2764 最小路径覆盖问题

    题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...

  5. POJ1061:青蛙的约会——题解

    http://poj.org/problem?id=1061 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定 ...

  6. XXE漏洞攻击与防御整理

    一.漏洞原理 1.DTD 文档类型定义(DTD)可定义合法的XML文档构建模块.它使用一系列合法的元素来定义文档的结构.DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用. 内部的 DOC ...

  7. 【BZOJ4889】[Tjoi2017]不勤劳的图书管理员 分块+树状数组

    [BZOJ4889][Tjoi2017]不勤劳的图书管理员 题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让 ...

  8. HDU 4417 离线+树状数组

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. bzoj1177 [Apio2009]Oil 二维前缀最大值,和

    [Apio2009]Oil Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2300  Solved: 932[Submit][Status][Disc ...

  10. lightoj 1282 && uva 11029

    Leading and Trailing lightoj 链接:http://lightoj.com/volume_showproblem.php?problem=1282 uva 链接:http:/ ...