51nod-1462: 树据结构
【传送门:51nod-1462】
简要题意:
给出一棵n个点的树,每个点有两个权值v,t
有Q个操作,有两种操作:
1.将x到根上的路径上的点的v值都加上d
2.将x到根上的路径上的点的t值都加上每个点的v值*d
最后求出所有点的t值
题解:
显然可以直接树链剖分做,不过lazy标记下放真麻烦,因为操作有互相影响
发现一种神标记方法——用矩阵
对于一个点,它的信息表示为$$ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ v & t & 1 \\ \end{matrix} $$
而对于第一种操作,就将点的信息乘上$$ \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ d & 0 & 1 \\ \end{matrix} $$
而第二种操作则乘上$$ \begin{matrix} 1 & d & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{matrix} $$
这样就不用担心互相影响了,因为矩阵乘法满足结合律,所以直接将操作按顺序乘起来就行了
听说可以离线CDQ做
参考代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
struct trnode
{
int l,r,lc,rc;
}tr[];int trlen;
struct Matrix
{
LL a[][];
Matrix()
{
memset(a,,sizeof(a));
}
}D[],cmp;
Matrix multi(Matrix a,Matrix b)
{
Matrix c;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
for(int k=;k<=;k++)
{
c.a[i][j]+=a.a[i][k]*b.a[k][j];
}
}
}
return c;
}
void bt(int l,int r)
{
trlen++;int now=trlen;
tr[now].l=l;tr[now].r=r;
D[now].a[][]=D[now].a[][]=D[now].a[][]=;
tr[now].lc=tr[now].rc=-;
if(l<r)
{
int mid=(tr[now].l+tr[now].r)/;
tr[now].lc=trlen+;bt(l,mid);
tr[now].rc=trlen+,bt(mid+,r);
}
}
struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y){a[++len]=(node){x,y,last[x]};last[x]=len;}
int son[],tot[];
void dfs1(int x)
{
tot[x]=;son[x]=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
dfs1(y);
if(tot[y]>tot[son[x]]) son[x]=y;
tot[x]+=tot[y];
}
}
int top[],ys[],z;
void dfs2(int x,int tp)
{
ys[x]=++z;top[x]=tp;
if(son[x]!=) dfs2(son[x],tp);
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=son[x]) dfs2(y,y);
}
}
void update(int now)
{
int lc=tr[now].lc,rc=tr[now].rc;
if(lc!=-) D[lc]=multi(D[lc],D[now]);
if(rc!=-) D[rc]=multi(D[rc],D[now]);
memset(D[now].a,,sizeof(D[now].a));
D[now].a[][]=D[now].a[][]=D[now].a[][]=;
}
void change(int now,int l,int r)
{
if(tr[now].l==l&&tr[now].r==r)
{
D[now]=multi(D[now],cmp);
return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/;
update(now);
if(r<=mid) change(lc,l,r);
else if(l>mid) change(rc,l,r);
else change(lc,l,mid),change(rc,mid+,r);
}
int fa[];
void solve(int x)
{
int tx=top[x];
while(x!=)
{
change(,ys[tx],ys[x]);
x=fa[tx];tx=top[x];
}
}
LL d[];
void out(int now)
{
if(tr[now].l==tr[now].r)
{
d[tr[now].l]=D[now].a[][];
return ;
}
int lc=tr[now].lc,rc=tr[now].rc;
update(now);
if(lc!=-) out(lc);
if(rc!=-) out(rc);
}
int main()
{
int n;
scanf("%d",&n);
len=;memset(last,,sizeof(last));
for(int i=;i<=n;i++)
{
scanf("%d",&fa[i]);
ins(fa[i],i);
}
dfs1();
z=;dfs2(,);
trlen=;bt(,z);
cmp.a[][]=cmp.a[][]=cmp.a[][]=;
int Q;
scanf("%d",&Q);
while(Q--)
{
int t,x;LL d;
scanf("%d%d%lld",&t,&x,&d);
if(t==) cmp.a[][]=,cmp.a[][]=d,solve(x);
else cmp.a[][]=,cmp.a[][]=d,solve(x);
}
out();
for(int i=;i<=n;i++) printf("%lld\n",d[ys[i]]);
return ;
}
51nod-1462: 树据结构的更多相关文章
- 51nod 1462 树据结构 | 树链剖分 矩阵乘法
题目链接 51nod 1462 题目描述 给一颗以1为根的树. 每个点有两个权值:vi, ti,一开始全部是零. Q次操作: 读入o, u, d o = 1 对u到根上所有点的vi += d o = ...
- 树状结构Java模型、层级关系Java模型、上下级关系Java模型与html页面展示
树状结构Java模型.层级关系Java模型.上下级关系Java模型与html页面展示 一.业务原型:公司的组织结构.传销关系网 二.数据库模型 很简单,创建 id 与 pid 关系即可.(pid:pa ...
- 分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限
大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码. 因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见. ...
- 由简入繁实现Jquery树状结构
在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便.但是利用Jquery的一些插件,也是可以实现这些效果的,比 ...
- php实现树状结构无级分类
php实现树状结构无级分类 ).",'树2-1-1-2')";mysql_query($sql);?>
- Android无限级树状结构
通过对ListView简单的扩展.再封装,即可实现无限层级的树控件TreeView. package cn.asiontang.nleveltreelistview; import android.a ...
- dzzoffice的树型结构用户管理设计
在DzzOffice1.1的开发中,针对用户使用群体重新设计了,机构.部门.用户管理应用. 传统OA,企业相关程序,一般是设置机构-设置部门-设置职位-添加用户这样的步骤.每个步骤分为不同的管理界面. ...
- 使用Map辅助拼装树状结构,消除递归调用
目前菜单或其他树状结构在数据库中的存储,多数是以一个parentid作为关联字段,以一维形式存储.使用时全部查询出来,然后在内存中拼装成树状结构.现在主要涉及的是拼装方法的问题. 一般可以进行 递归调 ...
- lua 怎样输出树状结构的table?
为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...
- js List<Map> 将偏平化的数组转为树状结构并排序
数据格式: [ { "id":"d3e8a9d6-e4c6-4dd8-a94f-07733d3c1b59", "parentId":&quo ...
随机推荐
- iOS数组越界
数组越界就是假如你的下标总数现在为32个,然后你在下一秒又执行了一个方法要从50个数据里进行赋值啊筛选之类的,而你此时数组里的值为32个,50的数据还没有请求到,往往会出现数组越界的崩溃信息,大概是这 ...
- java使用FileUtils文件操作神器
前言: 在工作当中我们往往遇到很多文件的操作,我们也习惯写一些自己定义的工具类来简化文件操作,其实apache的commons的FileUtils类就是这样一个工具类,使用它能大大的简化我们对文件的操 ...
- linux下恢复被删除的文件
https://cloud.tencent.com/developer/article/1028317
- Android之Action Bar
Action Bar在实际应用中,很好地为用户提供了导航,窗口位置标识,操作点击等功能.它出现于Android3.0(API 11)之后的版本中,在2.1之后的版本中也可以使用. 添加与隐藏Actio ...
- P1410 子序列
题目描述 给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列, 输入输出格式 输入格式: 若干行,每行表示一组数据.对于每组数据,首先输入一个整数N,表示序列的长度. ...
- 12) 十分钟学会android--APP通信传递消息之简单数据传输
程序间可以互相通信是Android程序中最棒的功能之一.当一个功能已存在于其他app中,且并不是本程序的核心功能时,完全没有必要重新对其进行编写. 本章节会讲述一些通在不同程序之间通过使用Intent ...
- ubuntu 16.04 php5 环境搭建
Ubuntu 16.04默认安装php7.0环境,但是php7目前兼容性并不是很好,如果自行安装php5需要清除php7的已安装包,否则会报错. 移除默认及已安装的PHP包 sudo dpkg -l ...
- mongoDB 介绍(特点、优点、原理)
介绍:MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. 特点:高性能.易部署.易使用,存储数据非常方便. 主要功能特性有: Ø 面 ...
- Android对手尽皆铩羽,鸿蒙如何绝地求生?
Android对手尽皆铩羽,鸿蒙如何绝地求生? 作为华为绝地反击备胎计划中的重要组成部分,鸿蒙被国人寄予了厚望.但是,除了热情我们更应该理性关注,鸿蒙对决Android未来有几成胜算?还有哪些问题需要 ...
- DNS解析过程详解(转载)
DNS解析过程详解(转载) DNS Domain Name System 域名系统,它就是根据域名查出IP地址. 先说一下DNS的几个基本概念: 一. 根域 就是所谓的“.”,其实我们的网址ww ...