noip模拟赛 洗衣
分析:好神的一道题啊.对每棵树建个图跑一下floyd可以有40分,想要打出正解就得对树有比较深的认识了.
每次新生成一棵树都是由两棵树i,j拼成的,答案为原来两棵树的答案和+i中每个点到j中每个点的距离和.显然这个距离和不能直接算,涉及到求整体的值,通常考虑每条边的贡献.设i,j两棵树的连接点为p,q,边长为l.l对答案的贡献是i的点数*j的点数*l.i中每个点要走到j里面,必须要先走到p上,i中的每个点对它走过的路径的贡献是j的点数*路径的边权,因为每条路径都被若干个点经过,所以算出i中所有点到p的距离和乘上j的点数就是i中的边对答案的贡献.j中所有边对答案的贡献也是这样算的.
那么怎么求树i中所有点到t的距离和呢?还是可以把树i拆分成两棵子树x,y.如果p在i的左子树中,那么就是连接点p到t的距离加上连接x,y的边的长度l的和乘上y中的点数加上y中所有点到q的距离和加上x中所有点到t的距离和.这实际上就相当于拆成了3部分:1是x里面的所有点到t去,2是y中的所有点到q去,3是y中所有点聚集到q后一起到t.如果p在i的右子树中,做法类似,递归地算下去.
那么怎么求p到t的距离呢?还是分两个点所在的树来讨论.如果p,t在同一子树,就在同一子树内递归算,如果在不同子树就先到连接点,然后再走过去,和之前的做法差不多.
因为求得的东西要经常被用到,所以需要记录状态的,可是m≤60,点的个数可能多达2^60个,这该怎么记录......其实需要记录的只有连接点的状态,但是连接点的编号可能很大,也会爆空间,一个很神的技巧就是在map中保存状态orz.开long long就能存下了.
丧心病狂的一道题,求两棵树任意两点之间的距离和的做法在树形dp中比较常见,需要记一下.黑科技map可以记录不多,但是表示起来很大的状态.
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll; const int mod = 1e9 + ; struct node
{
ll p, p1, p2;
node(){}
node(ll a, ll b, ll c)
{
p = a;
if (b < c)
{
p1 = b;
p2 = c;
}
else
{
p1 = c;
p2 = b;
}
}
bool operator < (const node & a) const {
if (p != a.p)
return p < a.p;
if (p1 != a.p1)
return p1 < a.p1;
return p2 < a.p2;
}
}; int n;
ll id1[], id2[], num1[], num2[], l[], sizee[];
ll ans[]; map <pair< ll, ll > , ll > m;
map <node, ll> m2; ll solve2(ll p, ll p1, ll p2)
{
if (!p)
return ;
if (p1 == p2)
return ;
node temp = node(p, p1, p2);
if (m2.count(temp))
return m2[temp];
if (p1 < sizee[id1[p]])
{
if (p2 < sizee[id1[p]])
m2[temp] = solve2(id1[p], p1, p2);
else
m2[temp] = (solve2(id1[p], num1[p], p1) + solve2(id2[p], num2[p], p2 - sizee[id1[p]]) + l[p]) % mod;
}
else
{
if (p2 < sizee[id1[p]])
m2[temp] = (solve2(id1[p], num1[p], p2) + solve2(id2[p], num2[p], p1 - sizee[id1[p]]) + l[p]) % mod;
else
m2[temp] = solve2(id2[p], p1 - sizee[id1[p]], p2 - sizee[id1[p]]);
}
return m2[temp];
} ll solve(ll p, ll n)
{
if (p == )
return ;
pair <ll, ll> t = make_pair(p, n);
if (m.count(t))
return m[t];
if (n < sizee[id1[p]])
{
ll temp1 = (solve2(id1[p], num1[p], n) + l[p]) % mod;
ll temp2 = temp1 * (sizee[id2[p]] % mod) % mod;
ll temp3 = (solve(id2[p], num2[p]) + solve(id1[p], n)) % mod;
m[t] = (temp2 + temp3) % mod;
}
else
{
ll temp1 = (solve2(id2[p], num2[p], n - sizee[id1[p]]) + l[p]) % mod;
ll temp2 = temp1 * (sizee[id1[p]] % mod) % mod;
ll temp3 = (solve(id1[p], num1[p]) + solve(id2[p], n - sizee[id1[p]])) % mod;
m[t] = (temp2 + temp3) % mod;
}
return m[t];
} int main()
{
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%lld%lld%lld%lld%lld", &id1[i], &id2[i], &num1[i], &num2[i], &l[i]);
sizee[] = ;
for (int i = ; i <= n; i++)
sizee[i] = sizee[id1[i]] + sizee[id2[i]];
for (int i = ; i <= n; i++)
{
ll temp1 = solve(id1[i], num1[i]) * (sizee[id2[i]] % mod) % mod;
ll temp2 = (sizee[id1[i]] % mod )* (sizee[id2[i]] % mod) % mod * l[i] % mod;
ll temp3 = solve(id2[i], num2[i]) * (sizee[id1[i]] % mod) % mod;
ans[i] = (((((((temp1 + temp2) % mod) + temp3) % mod) + ans[id1[i]]) % mod) + ans[id2[i]]) % mod;
}
for (int i = ; i <= n; i++)
printf("%lld\n", ans[i]);
return ;
}
noip模拟赛 洗衣的更多相关文章
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
- 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...
- 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...
随机推荐
- 17年day2
/* 嗯,明天就出发了. 嗯,终于快要结束了. 考试日常挂T1 今天晚上老师们请我们吃水饺,还有一个大蛋糕. 虽然没怎么吃蛋糕23333 还好我的水饺是白菜馅的~~~ 晚上学哥学姐们发视频送祝福,谢谢 ...
- [Swift通天遁地]一、超级工具-(19)制作六种别具风格的动作表单
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 认识BACnet协议
一.什么是BACnet? BACnet,Building Automation and Control networks的简称,即楼宇自动化与控制网络.是用于智能建筑的通信协议. 一般楼宇自控设备从功 ...
- Nginx开启http2访问和gzip网页压缩功能
准备工作 如果Nginx要开启http2需要满足以下2个条件: nginx >=1.9.5 openSSL >= 1.0.2 所以这里我们首先要检查Nginx的版本如果没有安装要先安装 ...
- MongoDB Built-In Roles(内置角色)
1. 数据库用户角色:read.readWrite; 2. 数据库管理角色:dbAdmin.dbOwner.userAdmin: 3. 集群管理角色:clusterAdmin.clusterManag ...
- C#将类对象转换为字典
主要是实现将类里面 的属性和对应的值转换为字典的键和值. public class RDfsedfw { /// <summary> /// 将匿名类转换为字典 /// </summ ...
- LN : leetcode 515 Find Largest Value in Each Tree Row
lc 515 Find Largest Value in Each Tree Row 515 Find Largest Value in Each Tree Row You need to find ...
- C语言指针的理解以及指针的指针的理解
指针指向的是内存地址编号,内存地址编号指向的是对应的内容. 我们需要一个变量,来储存内存地址编号,这个变量的值是一个内存地址编号,但是我们可以通过修改变量的值,来不断的改变内存地址编号. 但是,我们如 ...
- webview页面间的通信问题
前提 记一次多页面开发. 开发需求时会对页面刷新(reload),返回到上一页(用户返回 / history.go()) 页面间的通信 sessionStorage保存本次会话的信息,同步到新页面或上 ...
- UVM基础之------uvm_port_base
Port Base Classes uvm_port_component_base This class defines an interface for obtaining a port ...