Sometimes Naive

Problem Description
 
Rhason Cheung had a naive problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help.

She has a tree with n vertices, numbered from 1 to n. The weight of i-th node is wi.

You need to support two kinds of operations: modification and query.

For a modification operation u,w, you need to change the weight of u-th node into w.

For a query operation u,v, you should output ∑ni=1∑nj=1f(i,j). If there is a vertex on the path from u to v and the path from i to j in the tree, f(i,j)=wiwj, otherwise f(i,j)=0. The number can be large, so print the number modulo 109+7

 
Input
There are multiple test cases.

For each test case, the first line contains two numbers n,m(1≤n,m≤105).

There are n numbers in the next line, the i-th means wi(0≤wi≤109).

Next n−1 lines contain two numbers each, ui and vi, that means that there is an edge between ui and vi.

The following are m lines. Each line indicates an operation, and the format is "1 u w"(modification) or "2 u v"(query)(0≤w≤109)

 
Output
For each test case, print the answer for each query operation.
 
Sample Input
6 5
1 2 3 4 5 6
1 2
1 3
2 4
2 5
4 6
2 3 5
1 5 6
2 2 3
1 1 7
2 2 4
 
Sample Output
341
348
612
 

题意:

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

  要求支持两种操作:

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

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

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 1e6+, M = 1e3+, mod = 1e9+, inf = 2e9; LL aa[N],bb[N],in[N],out[N];
int dep[N],head[N],t=,sz[N],fa[N],indexS,top[N],pos[N],son[N];
struct ss{int to,next;}e[N*];
int n;
void add(int u,int v)
{e[t].to = v;e[t].next = head[u];head[u] = t++;} void dfs(int u) {
int k = ;
sz[u] = ;
if(u!=)dep[u] = dep[fa[u]] + ;
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(to == fa[u]) continue;
fa[to] = u;
dfs(to);
sz[u] += sz[to];
if(sz[to] > sz[k]) k = to;
}
if(k) son[u] = k;
}
void dfs(int u,int chain) {
int k = ;
pos[u] = ++indexS;
in[u] = indexS;
top[u] = chain;
if(son[u] > )
dfs(son[u],chain);
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(dep[to] > dep[u] && son[u] != to)
dfs(to,to);
}
out[u] = indexS;
} void update(int x,LL val,LL *sum) {
for(int i = x; i < N; i += i&(-i)) {
sum[i] += val;
sum[i] %= mod;
}
}
LL ask(int x,LL *sum) {
LL res = ;
for(int i = x; i; i-=i&(-i)) res += sum[i],res %= mod;
return res;
} LL allsum,C_tree[N],C_sqtree[N],a[N];
void update(int x,LL val) {
int u = top[x];
while(fa[u] > ) {
LL all = ask(out[u],C_tree) - ask(in[u]-,C_tree);
LL newall = (val - a[x])*(val - a[x])%mod + 1LL**all*(val-a[x])%mod;
update(in[fa[u]],newall%mod,C_sqtree);
u = top[fa[u]];
}
update(in[x],val-a[x],C_tree);
a[x] = val;
}
LL query(int x,int y) {
LL res = ,hav = ;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
res += ask(in[x],C_sqtree) - ask(in[top[x]]-,C_sqtree);
res %= mod;
if(son[x]>) {
LL all = ask(out[son[x]],C_tree) - ask(in[son[x]]-,C_tree);
res += all*all;
res %= mod;
}
if(hav>) {
LL all = ask(out[hav],C_tree) - ask(in[hav]-,C_tree);
res -= all * all;
res %= mod;
}
hav = top[x];
x = fa[hav];
}
if(dep[x] < dep[y]) swap(x,y);
res += ask(in[x],C_sqtree) - ask(in[y]-,C_sqtree);
res %= mod;
if(fa[y] > ) {
LL all = ((ask(out[],C_tree) - ask(out[y],C_tree) + ask(in[y]-,C_tree))%mod+mod)%mod;
res += (all*all)%mod;
res %= mod;
}
if(son[x]>) {
LL all = ask(out[son[x]],C_tree) - ask(in[son[x]]-,C_tree);
res += all*all;
res %= mod;
}
if(hav>) {
LL all = ask(out[hav],C_tree) - ask(in[hav]-,C_tree);
res -= all * all;
res %= mod;
}
return res;
}
int Q;
void init() {
memset(head,,sizeof(head));
t = ;
indexS = ;
allsum = ;
memset(son,-,sizeof(son));
son[] = ;
memset(C_tree,,sizeof(C_tree));
memset(C_sqtree,,sizeof(C_sqtree));
}
int main() {
while(scanf("%d%d",&n,&Q)!=EOF) {
init();
for(int i = ; i <= n; ++i)
scanf("%I64d",&a[i]);
allsum = allsum*allsum%mod;
for(int i = ; i < n; ++i) {
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
fa[] = -;
dfs();
dfs(,);
for(int i = ; i <= n; ++i) {
LL uu = a[i];
a[i] = ;
update(i,uu);
}
while(Q--) {
int op,x;
LL y;
LL all = ask(out[],C_tree);
scanf("%d%d%I64d",&op,&x,&y);
if(op == ) {
update(x,y);
}
else
printf("%I64d\n",((all*all%mod - query(x,y)) % mod + mod)%mod);
}
}
return ;
}

HDU 5405 Sometimes Naive 树链剖分+bit*****的更多相关文章

  1. 2015多校第9场 HDU 5405 Sometimes Naive 树链剖分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5405 题意: 给你一棵n个节点的树,有点权.        要求支持两种操作: 操作1:更改某个节点的 ...

  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. hdu 5242——Game——————【树链剖分思想】

    Game Time Limit:1500MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status  ...

  8. hdu 5242 Game(树链剖分,贪心¥)

    Game Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. HDU 3237 Tree(树链剖分)(线段树区间取反,最大值)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9123   Accepted: 2411 Description ...

随机推荐

  1. KNN算法原理及实现

    1.KNN算法概述 kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类决策上只依据最邻近的一 ...

  2. Java基础学习总结(92)——Java编码规范之排版、注释及命名

    为使开发人员养成良好的开发习惯,编写可读性强.易维护的程序,结合以往资料,现整理Java编码规范,将之作为开发人员的参照依据. 一.排版 1.相对独立的程序块之间必须加空行 下列情况应该使用一个空行: ...

  3. javascript:与获取鼠标位置有关的属性

    javascript并没有mouse对象,获取鼠标坐标要靠强大的event对象。 我们通过监听document的mousemove,就可以实时获得鼠标位置。 但是!!event中和鼠标相关的属性太多了 ...

  4. ssh 监听多个端口

    修改sshd的配置文件 默认位置:/etc/ssh/sshd_config 注释掉 Port 这行   然后添加 ListenAddress 行 e.g:  ListenAddress 192.168 ...

  5. K-means算法-聚类

    算法过程如下: 1)从N个文档随机选取K个文档作为质心 2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类 3)重新计算已经得到的个各类的质心 4)迭代2~3步直至新的质心与原质心相 ...

  6. 搜狗大数据总监、Polarr 联合创始人关于深度学习的分享交流 | 架构师小组交流会

    架构师小组交流会是由国内知名公司技术专家参与的技术交流会,每期选择一个时下最热门的技术话题进行实践经验分享.第一期:来自沪江.滴滴.蘑菇街.扇贝架构师的 Docker 实践分享 第二期:来自滴滴.微博 ...

  7. 【2017多校训练2+计算几何+板】HDU 6055 Regular polygon

    http://acm.hdu.edu.cn/showproblem.php?pid=6055 [题意] 给定n个格点,问有多少个正多边形 [思路] 因为是格点,只可能是正方形 枚举正方形的对角线,因为 ...

  8. lubuntu通过Smb访问Windows共享目录

    lubuntu通过Smb访问Windows共享目录 如果未安装Smb,先安装: apt-get install smbclient smbfs 安装后,查看共享主机上的共享目录: CentOS/Red ...

  9. Codeforces889C. Maximum Element

    $n \leq 2000000$的排列,问有多少满足:存在个$i$,使得$p_i \neq n$,且$p_j<p_i,j \in [i+1,i+K]$,$K \leq 2000000$是给定常数 ...

  10. Gearman 初窥【转载】

    Gearman是一个分发任务的程序框架,可以用在各种场合,与Hadoop相 比,Gearman更偏向于任务分发功能.它的任务分布非常简单,简单得可以只需要用脚本即可完成.Gearman最初用于Live ...