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 ...
随机推荐
- 《JavaScript权威指南》读书笔记(二)
日期:2015-12-04 js 的原型::闭包:闭包这是个相当复杂的东西...现在初步理解: http://segmentfault.com/a/1190000000652891 闭包有 ...
- 弹出消息对话框ScriptManager
//直接调用WebMessageBox方法 #region 弹出消息对话框 /// <summary> /// 弹出消息对话框 /// </summary> /// <p ...
- jQuery Easing动画效果扩展(转)
jQuery API提供了简单的动画效果如淡入淡出以及自定义动画效果,而今天我给大家分享的是一款jQuery动画效果扩展增强插件jquery.easing.js,使用该插件可以实现直线匀速运功.变加速 ...
- java面试---summay
1:合适的建立索引,数据量比较大的时候,如果频繁的进行修改插入则不建议建立索引! 2:什么时候适合建索引,在什么字段上面建立索引? (被当做查询条件的) 3:什么叫做编译错误,什么叫做运行时异常 能被 ...
- 读取DBF文件的部分代码
private void BtnOpenInitial_Click(object sender, EventArgs e) { OpenFileDialog file = new OpenFileDi ...
- VS2010 winform程序发布步骤
1.右键单击解决方案,点击“添加”---“新建项目”,如下图: 2.选择“其他项目类型”--“安装和部署”--“Visual Studio Installer”---"安装项目", ...
- 深入理解Redis:命令处理流程
Redis是著名的NoSQL键值数据库服务器,为了保证效率,其数据都缓存在内存中.与Memcached相比,Redis支持的数据类型更多,包括String,List,Set,Zset和Hash.下面简 ...
- 一个快速查看API的汇编和机器码的工具.发布源码
提供一个早年写的一个小工具,一直在用,赶紧很顺手,特推荐给大家. 欢迎垂询. 1,在OD正在跟踪分析某个保护壳的一段code的时候,感觉似曾相识,好像在哪里见过,好像是某个API.----这个时候你就 ...
- 二模 (5)day1
第一题: 题目大意:解一元一次方程(只有+-符号): 解题过程:直接处理处两边的x的系数和常数项,字符串的处理即可. 第二题: 题目大意:求逆序对数. 解题过程:直接归并排序. 第三题: 题目大意:多 ...
- DataGridView复选框实现单选功能(二)
双击DataGridView进入事件 private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventA ...