HDU 5405 (树链剖分+线段树)
Problem Sometimes Naive
题目大意
给你一棵n个节点的树,有点权。
要求支持两种操作:
操作1:更改某个节点的权值。
操作2:给定u,v, 求 Σw[i][j] i , j 为任意两点且i到j的路径与u到v的路径相交。
解题分析
容易发现对于一个询问,答案为总点权和的平方 减去 去掉u--v这条链后各个子树的点权和的平方的和。
开两棵线段树,tag1记录点权和,tag2记录某点的所有轻链子树的点权和的平方的和。
每次沿着重链往上走时,直接加上这条重链的所有点的tag2和,若有重儿子则直接用tag1计算。由于该条重链必定为其父亲的轻链,故为防止计算重复,还需减去该重链所有点的tag1平方和。
最后爬到同一颗重链后,还需计算重链上方所有点的贡献。
参考程序
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std; #define V 100008
#define E 200008
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define clr(x,v) memset(x,v,sizeof(x));
#define rep(x,y,z) for (int x=y;x<=z;x++)
#define repd(x,y,z) for (int x=y;x>=z;x--)
const int mo = ;
const int inf = 0x3f3f3f3f;
const int INF = ;
/**************************************************************************/
int n,m,tot;
int val[V];
int size[V],fa[V],w[V],top[V],rk[V],dep[V],son[V]; struct line{
int u,v,nt;
line(int u=,int v=,int nt=):u(u),v(v),nt(nt){}
}eg[E];
int lt[V],sum; void add(int u,int v){
eg[++sum]=line(u,v,lt[u]); lt[u]=sum;
} struct Segment_Tree{
LL sum[V<<];
void clear(){
clr(sum,);
}
void pushup(int rt){
sum[rt] = (sum[rt<<] + sum[rt<<|]) % mo;
}
void update(int x,int val,int l,int r,int rt){
if (l==r){
sum[rt] += val;
sum[rt] = sum[rt] % mo;
return;
}
int m=(l+r)>>;
if (x <= m) update(x,val,lson);
if (m < x) update(x,val,rson);
pushup(rt);
}
LL query(int L,int R,int l,int r,int rt){
if (L<=l && r<=R){
return sum[rt];
}
int m=(l+r)>>;
LL res=;
if (L <= m) res += query(L,R,lson);
if (m < R) res += query(L,R,rson);
res = res % mo;
return res;
} }Ts,Td;
void init(){
clr(lt,); sum=; tot=;
Ts.clear();
Td.clear();
}
void dfs_1(int u){
dep[u]=dep[fa[u]]+; size[u]=; son[u]=;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u]) continue;
fa[v]=u;
dfs_1(v);
if (size[v]>size[son[u]]) son[u]=v;
size[u]+=size[v];
}
} void dfs_2(int u,int tp){
top[u]=tp; w[u]=++tot; rk[tot]=u;;
if (son[u]) dfs_2(son[u],tp);
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u]||v==son[u]) continue;
dfs_2(v,v);
}
} int sqr(int x){return 1ll*x*x %mo;}
void update(int x,int v){
int u=top[x];
while (fa[u]){
LL sum=Ts.query(w[u],w[u]+size[u]-,,n,);
Td.update(w[fa[u]],(sqr(val[x]-v)-sum**(val[x]-v) % mo)%mo,,n,);
u=top[fa[u]];
}
Ts.update(w[x],v-val[x],,n,);
val[x]=v;
}
LL query(int x,int y){
LL res=;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
res += Td.query(w[top[x]],w[x],,n,);
res = res % mo; if (son[x]){
LL sum=Ts.query(w[son[x]],w[son[x]]+size[son[x]]-,,n,);
res = res + sum*sum;
res = res % mo;
}
LL sum=Ts.query(w[top[x]],w[top[x]]+size[top[x]]-,,n,); res = res - sum*sum;
res = res % mo;
while (res<) res+=mo;
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
res += Td.query(w[x],w[y],,n,);
res = res % mo;
if (son[y]){
LL sum=Ts.query(w[son[y]],w[son[y]]+size[son[y]]-,,n,);
res = res + sum*sum;
res = res % mo;
}
if (fa[x]){
LL sum=Ts.query(,n,,n,)-Ts.query(w[x],w[x]+size[x]-,,n,);
res = res + sum*sum;
res = res % mo;
}
return res;
} int main(){
while (~scanf("%d %d",&n,&m)){
init();
rep(i,,n) scanf("%d",&val[i]);
rep(i,,n){
int u,v;
scanf("%d %d",&u,&v);
add(u,v); add(v,u);
}
dfs_1();
dfs_2(,);
rep(i,,n){
int k=val[i];
val[i]=;
update(i,k);
}
while (m--){
int x,u,v;
scanf("%d %d %d",&x,&u,&v);
if (x==) update(u,v);
else {
LL sum=Ts.query(w[],w[]+size[]-,,n,);
sum = sum * sum;
sum = sum - query(u,v);
sum = sum % mo;
while (sum<) sum+=mo;
printf("%lld\n",sum);
}
}
}
}
HDU 5405 (树链剖分+线段树)的更多相关文章
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- 弹出消息对话框ScriptManager
//直接调用WebMessageBox方法 #region 弹出消息对话框 /// <summary> /// 弹出消息对话框 /// </summary> /// <p ...
- Java 线程综述
线程重在 线程同步和线程通信的编程 1.线程与进程? 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.线程的状态:运行.就绪.挂起(suspend).结束; 进程是指一段正在执行的程序. ...
- 大作业关于(“有爱”youi)的简介
我们团队一共四个人,我们足够了解对方的优缺点,能够很好的进行交流沟通.对于一些问题也能有好的方法去解决,我做事情比较讲究高效和尽可能的完美,或者说要做到我自己觉得完美,才会停下来.对于一件事情,我有自 ...
- PHP超级全局变量——Session 变量
PHP session 变量用于存储有关用户会话的信息,或更改用户会话的设置.Session 变量保存的信息是单一用户的,并且可供应用程序中的所有页面使用. PHP Session 变量 当您运行一个 ...
- GO工程和包
转载:http://blog.csdn.net/achelloworld/article/details/43956831 在Go语言中,包是函数与数据的集合,用package定义一个包,包的名字不一 ...
- AES加密 16进制与二进制转换
import java.security.Key; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax ...
- cisco 路由配置
Cisco路由配置基础 刚刚接触cisco路由配置,下面是学习的笔记,感觉命令还是多敲才能熟悉 一. 所处状态各类 router> 用户处于用户命令状态,可以查看网络和主机 router# 用户 ...
- qml支持多平台的编译--尤其对于需要支持xp的情况
http://www.oschina.net/p/deepin-boot-maker 系统支持: Windows平台: Windows 7/ Windows 8 需要安装显卡驱动 Windows XP ...
- 提升WordPress站点速度的八个建议
WordPress是一个很棒的开源程序,几乎我认识的站长朋友当中,粗略估算有80%使用Wordpress.但很棒不等于完美,就在我所认识的这些朋友中,几乎所有人都会抱怨Wordpress太臃肿,运行效 ...
- HDU 3076 ssworld VS DDD 概率dp,无穷级数,oj错误题目 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3076 不可思议的题目,总之血量越少胜率越高,所以读取时把两人的血量交换一下 明显每一轮的胜率和负率都是固定的,所 ...