hihocoder-1347 小h的树上的朋友(lca+线段树)
题目链接:
小h的树上的朋友
描述
小h拥有n位朋友。每位朋友拥有一个数值Vi代表他与小h的亲密度。亲密度有可能发生变化。
岁月流逝,小h的朋友们形成了一种稳定的树状关系。每位朋友恰好对应树上的一个节点。
每次小h想请两位朋友一起聚餐,他都必须把连接两位朋友的路径上的所有朋友都一起邀请上。并且聚餐的花费是这条路径上所有朋友的亲密度乘积。
小h很苦恼,他需要知道每一次聚餐的花销。小h问小y,小y当然会了,他想考考你。
输入
输入文件第一行是一个整数n,表示朋友的数目,从1开始编号。
输入文件第二行是n个正整数Vi,表示每位朋友的初始的亲密度。
接下来n-1行,每行两个整数u和v,表示u和v有一条边。
然后是一个整数m,代表操作的数目。每次操作为两者之一:
0 u v 询问邀请朋友u和v聚餐的花费
1 u v 改变朋友u的亲密度为v
1<=n,m<=5*105
Vi<=109
输出
对于每一次询问操作,你需要输出一个整数,表示聚餐所需的花费。你的答案应该模1,000,000,007输出。
- 样例输入
-
3
1 2 3
1 2
2 3
5
0 1 2
0 1 3
1 2 3
1 3 5
0 1 3 - 样例输出
-
2
6
15
题意:
中文的就不说了; 思路:
显然是一个线段树的题;
先dfs,把树映射到区间上同时求出每个点到根节点的花费,
0的时候询问:先找到lca;再dis[u]*dis[v]*w[lca]/(dis[lca]*dis[lca]);可以费马小定理快速幂求逆;
1的时候更新:dfs的时候找到了每个点的包含此点所以子节点的区间,把这个区间的dis都更新同时还要更新w[u]我就是这两个问题写漏了改了一夜晚; AC代码:#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=5e5+10;
const int maxn=1e3+10;
const double eps=1e-10; LL w[N],dis[N];
vector<int>ve[N]; int n,in[N],a[2*N],dep[N],cnt=0,out[N]; LL pow_mod(LL x,LL y)
{
LL s=1,base=x;
while(y)
{
if(y&1)s=s*base%mod;
base=base*base%mod;
y>>=1;
}
return s;
} void dfs(int x,int deep,int fa)
{
cnt++;
in[x]=cnt;
a[cnt]=x;
dep[x]=deep;
int len=ve[x].size();
For(i,0,len-1)
{
int y=ve[x][i];
if(y==fa)continue;
dis[y]=dis[x]*w[y]%mod;
dfs(y,deep+1,x);
cnt++;
a[cnt]=x;
}
out[x]=cnt;
}
struct Tree
{
int l,r,lca;
LL dis;
}tr[8*N];
void pushdown(int o)
{
tr[2*o].dis=tr[2*o].dis*tr[o].dis%mod;
tr[2*o+1].dis=tr[2*o+1].dis*tr[o].dis%mod;
tr[o].dis=1;
}
void build(int o,int L,int R)
{
tr[o].l=L;
tr[o].r=R;
tr[o].dis=1;
if(L==R)
{
tr[o].dis=dis[a[L]];
tr[o].lca=a[L];
return ;
}
int mid=(L+R)>>1;
build(2*o,L,mid);
build(2*o+1,mid+1,R);
if(dep[tr[2*o].lca]>=dep[tr[2*o+1].lca])tr[o].lca=tr[2*o+1].lca;
else tr[o].lca=tr[2*o].lca;
}
void update(int o,int L,int R,LL val)
{
if(tr[o].l>=L&&tr[o].r<=R)
{
tr[o].dis=tr[o].dis*val%mod;
return ;
}
int mid=(tr[o].l+tr[o].r)>>1; if(L>mid)update(2*o+1,L,R,val);
else if(R<=mid)update(2*o,L,R,val);
else {
update(2*o,L,mid,val);
update(2*o+1,mid+1,R,val);
}
}
int querylca(int o,int L,int R)
{ if(tr[o].l>=L&&tr[o].r<=R)return tr[o].lca;
int mid=(tr[o].l+tr[o].r)>>1;
if(R<=mid)return querylca(2*o,L,R);
else if(L>mid)return querylca(2*o+1,L,R);
else
{
int fl=querylca(2*o,L,mid),fr=querylca(2*o+1,mid+1,R);
if(dep[fl]<=dep[fr])return fl;
else return fr;
}
}
LL query(int o,int pos)
{
if(tr[o].l==tr[o].r&&tr[o].l==pos)return tr[o].dis;
int mid=(tr[o].l+tr[o].r)>>1;
pushdown(o);
if(pos>mid)return query(2*o+1,pos);
return query(2*o,pos);
}
int main()
{
read(n);
For(i,1,n)read(w[i]);
int u,v;
For(i,1,n-1)
{
read(u);read(v);
ve[u].push_back(v);
ve[v].push_back(u);
}
dis[1]=w[1];
dfs(1,0,0);
build(1,1,cnt);
int q,f;
read(q);
while(q--)
{
read(f);read(u);read(v);
if(f)
{
LL temp=w[u];
w[u]=(LL)v;
update(1,in[u],out[u],w[u]*pow_mod(temp,mod-2)%mod);
}
else
{
if(in[u]>in[v])swap(u,v);
int lca=querylca(1,in[u],in[v]);
LL temp=query(1,in[lca]);
temp=pow_mod(temp,mod-2);
temp=temp*temp%mod;
LL ans=query(1,in[u])*query(1,in[v])%mod*temp%mod*w[lca]%mod;
cout<<ans<<"\n";
}
}
return 0;
}
hihocoder-1347 小h的树上的朋友(lca+线段树)的更多相关文章
- hihocoder 1347 小h的树上的朋友
传送门 时间限制:18000ms单点时限:2000ms内存限制:512MB 描述 小h拥有$n$位朋友.每位朋友拥有一个数值$V_i$代表他与小h的亲密度.亲密度有可能发生变化.岁月流逝,小h的朋友们 ...
- 2018 ACMICPC上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节)
2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节) 链接:https://ac.nowcoder.co ...
- [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)
[51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
- [BZOJ3307]:雨天的尾巴(LCA+树上差分+权值线段树)
题目传送门 题目描述: N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式: 第一 ...
- 51nod 1463 找朋友 (扫描线+线段树)
1463 找朋友 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 难度:5级算法题 收藏 关注 给定: 两个长度为n的数列A .B 一个有m个元素的集合K 询问Q次 每次询 ...
- 51Nod1766 树上的最远点对 ST表 LCA 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1766.html 题目传送门 - 51Nod1766 题意 n个点被n-1条边连接成了一颗树,给出a~ ...
- 51nod 1463 找朋友(线段树+离线处理)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...
- [bzoj3306]树——树上倍增+dfs序+线段树
Brief Description 您需要写一种数据结构,支持: 更改一个点的点权 求一个子树的最小点权 换根 Algorithm Design 我们先忽略第三个要求. 看到要求子树的最小点权,我们想 ...
随机推荐
- 使用<sstream> 替代<stdio.h>
c++ 字符串流 sstream(常用于格式转换) 使用stringstream对象简化类型转换C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更 ...
- 531. Lonely Pixel I
Given a picture consisting of black and white pixels, find the number of black lonely pixels. The pi ...
- ubuntu下用webbench做网站压力测试
安装依赖 exuberant-ctags sudo apt-get install exuberant-ctags 下载源码并安装 wget http://blog.s135.com/soft/lin ...
- 转载免费的SSL证书
目前我知道的有2种方式进行免费的SSL证书的获取 第一种:腾讯云申请 第二种:Let's Encrypt (国外在) 我一直使用第一种,还可以,有效期1年. 以下转载第二种: 实战申请Let's En ...
- Java到底是值传递还是引用传递
什么是按值传递,什么是按引用传递 按值调用(call by value) : 在参数传递过程中,形参和实参占用了两个完全不同的内存空间.形参所存储的内容是实参存储内容的一份拷贝. 按引用调用:在参数传 ...
- sqlplus登陆scott用户,以及退出连接
进入sqlplus界面 即登陆成功,PLsql也一样 退出连接:
- Java的不定参数(eg:Object...)(转)
第一个例子: public class VariArgs { public static void main(String[] args) { test(); test("aaa" ...
- 【Spring boot】【gradle】idea新建spring boot+gradle项目
在此之前,安装了idea/jdk/gradle在本地 ===================================== gradle怎么安装:http://www.cnblogs.com/s ...
- kafka的安装和使用;kafka常用操作命令
kafka:基于发布/订阅的分布式消息系统.数据管道:最初用来记录活动数据--包括页面访问量(Page View).被查看内容方面的信息以及搜索情况等内容和运营数据--服务器的性能数据(CPU.IO使 ...
- 【转】 C++ 简单的 Tcp 实现[socket] 客户端与客户端通信
// 服务器端代码 // Server.cpp : Defines the entry point for the console application.// #include "std ...