[CF607D]Power Tree
题目大意:
一棵树初始只有一个编号为$1$的权值为$w_1$的根。$q(q\le2\times10^5)$次操作,每次可以给出$v,w(w<10^9)$,新建一个结点作为$v$的子结点,权值为$w$;或者给出$u$,求出$f(u)$。定义$f(u)=|S|\cdot\sum_{d\in S}d$,其中$S$为$w_u$与其所有子结点$v$的$f(v)$构成的可重集合。
思路:
首先将树全部建好,用线段树维护DFS序。每次新加结点相当于将这一结点的权值由$0$变为$w$,用线段树计算加上这个点以后的贡献。题目就变成了线段树上单点加、区间乘、区间求和问题。时间复杂度$O(q(\log n+\log w))$,其中$O(\log w)$是求逆元的复杂度。
#include<cstdio>
#include<cctype>
#include<forward_list>
using int64=long long;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
constexpr int N=2e5+,Q=2e5,mod=1e9+;
int w[N],n,dfn[N],par[N],size[N],s[N];
std::forward_list<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_front(v);
}
struct Operation {
int type,v,u;
};
Operation o[N];
void exgcd(const int &a,const int &b,int &x,int &y) {
if(!b) {
x=,y=;
return;
}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
int inv(const int &x) {
int ret,tmp;
exgcd(x,mod,ret,tmp);
return (ret%mod+mod)%mod;
}
void dfs(const int &x) {
size[x]=;
dfn[x]=++dfn[];
for(auto &y:e[x]) {
dfs(y);
size[x]+=size[y];
}
}
class SegmentTree {
#define _left <<1
#define _right <<1|1
private:
int val[N<<],tag[N<<];
void push_up(const int &p) {
val[p]=(val[p _left]+val[p _right])%mod;
}
void push_down(const int &p) {
if(tag[p]==) return;
tag[p _left]=(int64)tag[p _left]*tag[p]%mod;
tag[p _right]=(int64)tag[p _right]*tag[p]%mod;
val[p _left]=(int64)val[p _left]*tag[p]%mod;
val[p _right]=(int64)val[p _right]*tag[p]%mod;
tag[p]=;
}
public:
void build(const int &p,const int &b,const int &e) {
tag[p]=;
if(b==e) return;
const int mid=(b+e)>>;
build(p _left,b,mid);
build(p _right,mid+,e);
}
void add(const int &p,const int &b,const int &e,const int &x,const int &v) {
(val[p]+=v)%=mod;
if(b==e) return;
push_down(p);
const int mid=(b+e)>>;
if(x<=mid) add(p _left,b,mid,x,v);
if(x>mid) add(p _right,mid+,e,x,v);
}
void mul(const int &p,const int &b,const int &e,const int &l,const int &r,const int &v) {
if(b==l&&e==r) {
val[p]=(int64)val[p]*v%mod;
tag[p]=(int64)tag[p]*v%mod;
return;
}
push_down(p);
const int mid=(b+e)>>;
if(l<=mid) mul(p _left,b,mid,l,std::min(mid,r),v);
if(r>mid) mul(p _right,mid+,e,std::max(mid+,l),r,v);
push_up(p);
}
int query(const int &p,const int &b,const int &e,const int &l,const int &r) {
if(b==l&&e==r) {
return val[p];
}
push_down(p);
int ret=;
const int mid=(b+e)>>;
if(l<=mid) (ret+=query(p _left,b,mid,l,std::min(mid,r)))%=mod;
if(r>mid) (ret+=query(p _right,mid+,e,std::max(mid+,l),r))%=mod;
return ret;
}
#undef _left
#undef _right
};
SegmentTree t;
int main() {
w[n=]=getint();
const int q=getint();
for(register int i=;i<q;i++) {
o[i].type=getint();
if(o[i].type==) {
o[i].v=par[++n]=getint();
add_edge(par[n],n);
w[o[i].u=n]=getint();
}
if(o[i].type==) {
o[i].v=getint();
}
}
dfs();
s[]=;
t.build(,,n);
t.add(,,n,,w[]);
for(register int i=;i<q;i++) {
const int &y=o[i].u,&x=o[i].v;
if(o[i].type==) {
t.add(,,n,dfn[y],(int64)t.query(,,n,dfn[x],dfn[x])*inv(w[x])%mod*w[y]%mod);
t.mul(,,n,dfn[x],dfn[x]+size[x]-,(int64)inv(s[x])*(s[x]+)%mod);
s[x]+=s[y]=;
}
if(o[i].type==) {
const int ans=t.query(,,n,dfn[x],dfn[x]+size[x]-);
if(x==) {
printf("%d\n",ans);
continue;
}
printf("%d\n",int((int64)ans*w[par[x]]%mod*inv(t.query(,,n,dfn[par[x]],dfn[par[x]]))%mod));
}
}
return ;
}
[CF607D]Power Tree的更多相关文章
- CF1120D Power Tree
沙发~~ 题意简述 给你一棵有根树,定义叶子为度数为1的点. 你可以以$ w_x \(的代价控制\)x\(点.选择控制之后可以给它的子树里的叶子加 上\)t (t \in Z )$. 你要以最小的总代 ...
- Codeforces 1120D Power Tree [最小生成树]
洛谷 Codeforces 这题怎么一个中文题解都没有,是不是你们都认为太水了-- 思路 显然可以用dfs序把每个节点变成给一个区间的叶子节点加上某个数. 显然把叶子序列差分一下变为\(a_1,a_2 ...
- CF1120D Power Tree(构造题,差分,最小生成树)
很有趣的一道题. 首先可以对每个叶子进行编号.按照DFS到的顺序即可.(假设从 $1$ 到 $k$) 然后对每个点求出它管辖的所有叶子的编号.因为是DFS序所以这一定是个区间.设点 $u$ 的这个区间 ...
- cf Round 607
A.Chain Reaction(DP+二分) 题意:一排有n个灯塔,每个灯塔给出坐标xi和力量yi,每次从最右边依次点亮灯塔,每点亮一个灯塔,它左边的距离它yi范围内的灯塔将受到损坏.现在允许在最右 ...
- codeforces选做
收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...
- Codeforces Round #543 Div1题解(并不全)
Codeforces Round #543 Div1题解 Codeforces A. Diana and Liana 给定一个长度为\(m\)的序列,你可以从中删去不超过\(m-n*k\)个元素,剩下 ...
- Codeforces Round #539Ȟȟȡ (Div. 1) 简要题解
Codeforces Round #539 (Div. 1) A. Sasha and a Bit of Relax description 给一个序列\(a_i\),求有多少长度为偶数的区间\([l ...
- ZOJ 3684 Destroy 树的中心
中心节点就是树的中心,2遍dfs求到树的直径.而中心一定在直径上,顺着直径找到中心就够了. 然后能够一遍树形DP找到最小值或者二分+推断是否訪问到叶子节点. #include <iostream ...
- Codeforces Round #543 (Div. 1, based on Technocup 2019 Final Round) 题解
题面戳这里 A. Diana and Liana 首先如果s>ks>ks>k一定无解,特判一下.那么我们考虑找恰好满足满足题目中的要求的区间[l,r][l,r][l,r],那么需要要 ...
随机推荐
- MAVEN 编译打包测试 指定本地jar
转载自:http://penuel.iteye.com/blog/1766102 maven对于互联网开发,进行版本管理有着不可或缺的作用; 而经常开发的程序猿直接联调或者依赖未上线或deploy的 ...
- [洛谷P3501] [POI2010]ANT-Antisymmetry
洛谷题目链接:[POI2010]ANT-Antisymmetry 题目描述 Byteasar studies certain strings of zeroes and ones. Let be su ...
- 51nod 1020 逆序排列——dp
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...
- 25个常规方法优化你的jquery代码
原文发布时间为:2011-06-06 -- 来源于本人的百度文章 [由搬家工具导入] http://www.tvidesign.co.uk/blog/improve-your-jquery-25-ex ...
- 我在开发中所遇到的iOS7新特性以及iOS7与iOS6的适配问题总结
⓵UIImageView 1. // iOS7添加的对图像颜色处理的功能,过滤颜色的功能 2. _imageView.tintColor = [UIColor blueColor]; 3. //重 ...
- swift 之嵌套的理解 func chooseStepFunction(backwards: Bool) -> (Int) -> Int
http://blog.csdn.net/lzx_322/article/details/28861199 swift 函数使用前面需要添加 func 有返回值需要使用-> 后面添加返回类型 , ...
- SQLAlchemy ORM教程之二:Query
from:https://www.jianshu.com/p/8d085e2f2657 这是继SQLAlchemy ORM教程之一:Create后的第二篇教程.在上一篇中我们主要是解决了如何配置ORM ...
- maven中的pom.xml解析
pom.xml用于项目描述,组织管理,依赖管理和构件信息的管理. <project>是pom.xml的一些约束信息: <modelVersion>指定了当前pom的版本: 坐标 ...
- JS计算两个日期之间的天数
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 关于测试url传值的问题
url1:http://localhost:8080/fms/finan/isRiskCustomer.action?customername="xxxxxxxx"; 如上这样写, ...