【UR #7】水题走四方
题目描述
今天是世界水日,著名的水题资源专家蝈蝈大臣发起了水题走四方活动,向全世界发放成千上万的水题。
蝈蝈大臣是家里蹲大学的教授,当然不愿意出门发水题啦!所以他委托他的助手欧姆来发。
助手欧姆最近做 UR #6 被狗狗传染了懒癌,当然不愿意出门发水题啦!所以他请来了高手 —— 地卜师。
全世界一共 n 个城市,编号分别为 1,…,n。城市之间由双向道路相连,形成了一棵树。如果这棵树以 1 为根,则除 1 以外每个结点 v 的父亲结点的编号 pv 满足 pv<v。
由于地卜师掌握了克隆的核心科技,把自己完全复制了一份,他和他的分身一共两个地卜师一起出去执行任务。
现在,两个地卜师都站在 1 号城市。地卜师可以沿道路行走,从一个城市移动到另一个城市。走一条道路需要耗时 1 小时。当然,地卜师可以停留在某个城市不动。每到一个没有发放水题的城市,地卜师都会发水题。在一个城市里发水题的时间不计。
由于地卜师有强迫症,他沿道路移动时总是从一个城市移动到编号更大的城市。即总是从一个结点移动到它的儿子结点。地卜师和他的分身可以同时移动。
但是地卜师这样好像不一定能经过所有的城市?没关系!地卜师会瞬移。如果某个时刻两个地卜师都在某个城市里(而不是在去某个城市的道路上),那么其中一个地卜师可以瞬移到另一个地卜师所在的城市。瞬移所需的时间不计。
现在地卜师想知道,要想顺利给每个城市都发放水题,最短需要多少个小时。
欧姆当然知道怎么计算啦!但是他想考考你。
题解
神仙题.png。
我们可以先考虑最优解是怎么走出来的。
先是这个人和它的分身,初步的想法是他们俩来到了一个节点,然后分身去遍历这颗子树的一些儿子中的叶子结点。
最后剩一个儿子,然后它俩一块走到下一个儿子里面。
但是这种想法少考虑了一些情况(反例就不说了,也就是说不能只考虑往儿子走)。
我们可以将两个人同时停留的地方称作关键点,显然所有的关键点都在一条链上。
那么分身应该遍历这颗子树减去下一颗关键点所在子树的那颗子树的所有叶子结点。
就是在分身遍历最后一个叶子的时候,这个人可以同时往下一个关键点走,等到两个人都到了自己该到的地方,分身再TP到这个人那里。
然后有一个初步的dp想法,就是设dp[i]表示i是一个关键点,两个人第一次到这个点所用的最小时间。
转移:
nl:当前子树内的叶子节点个数,ds:当前子树内叶子结点的深度和,dm[u][v]:u的子树扣掉v的子树后最深的叶子结点的深度,d:节点深度。
更正:上面的第二个min为max。
后面那个东西是在讨论这个人和分身谁先到目的地。
这个dp是n^2的,好像有各种高科技的优化办法然而并不会。。。
我们发现这个式子前面那一坨好像可优化性不大。
考虑后面那个max可不可以为0,那么相当于是说找到一个祖先u使得d[v]<=dm[u,v]。
如果我们对于每个点都找出这个祖先的话,转移就轻松完成了。
我们考虑是不是所有点都能找到这个祖先,肯定不是的,当一个点的deep满足没有其他点和它deep相等时这个点是没有这种祖先的。
这样的点有什么神奇的规律?它们是连续的一条链,就是这个样子的。
一棵树下面多出来的这条链。
因为我们是在叶子的位置统计答案,那么有结论,最优解肯定不在这种叶子上(想想为什么)。
那么我们的任务就变成找这种神奇祖先了。
首先这种神奇祖先肯定是越低越好。
我们可以维护一个链表表示还没找到祖先的节点,在子树合并的时候互相更新一下(因为两颗子树的maxdeep都可以作为更新答案的条件)。
这是最多只会有一颗子树内有节点没有找到祖先(想想为什么),所以我们维护的复杂度是线性的。
代码
#include<iostream>
#include<cstdio>
#define N 5000009
#define inf 1e18
using namespace std;
typedef long long ll;
inline ll rd(){
ll x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
ll n,deep[N],mx_deep[N],sum_deep[N],cnt[N],dp[N];
int nxt[N],up[N],son[N],tot,fa[N];
char s[N<<];
int main(){
n=rd();
scanf("%s", s);int v;
for(int i=;i<n*;i++){
if(s[i]=='('){
tot++;
fa[tot]=v;
v=tot;
}
else v=fa[v];
}
for(int i=;i<=n;++i){
if(fa[i])son[fa[i]]++;
deep[i]=deep[fa[i]]+;
}
for(int i=n;i>=;--i){
if(!son[i]){
mx_deep[i]=sum_deep[i]=deep[i];
cnt[i]=;
}
int now=i;
while(now&&deep[now]<=mx_deep[fa[i]]){
up[now]=fa[i];
now=nxt[now];
}
while(nxt[fa[i]]&&deep[nxt[fa[i]]]<=mx_deep[i]){
up[nxt[fa[i]]]=fa[i];
nxt[fa[i]]=nxt[nxt[fa[i]]];
}
if(now)nxt[fa[i]]=now;
mx_deep[fa[i]]=max(mx_deep[fa[i]],mx_deep[i]);
sum_deep[fa[i]]+=sum_deep[i];
cnt[fa[i]]+=cnt[i];
}
ll ans=inf;
for(int i=;i<=n;++i){
dp[i]=inf;
if(up[i])dp[i]=dp[up[i]]+sum_deep[up[i]]-sum_deep[i]-(cnt[up[i]]-cnt[i])*deep[up[i]];
if(son[fa[i]]==)dp[i]=min(dp[fa[i]]+,dp[i]);
if(!son[i])ans=min(ans,dp[i]);
}
if(n==){puts("");return ;}
cout<<ans;
return ;
}
【UR #7】水题走四方的更多相关文章
- 【UR #7】水题走四方 题解
链接:http://uoj.ac/problem/84 20分算法:萌萌的小爆搜,别搜进环里就行. 50分:我们考虑一下最优决策是什么样的.看似很显然的一点就是我们先让本体在原地不动,让分身去遍历子树 ...
- 【UOJ#82】【UR #7】水题生成器(贪心)
[UOJ#82][UR #7]水题生成器(贪心) 题面 UOJ 题解 把\(n!\)的所有约数搜出来,这个个数不会很多. 然后从大往小能选则选就好了. #include<iostream> ...
- #82. 【UR #7】水题生成器
链接:http://uoj.ac/problem/82 今天是世界水日,著名的水题资源专家蝈蝈大臣向世界宣布了他的一项新发明 —— 水题生成器. 每道题目都有一个正整数的难度值.水题生成器虽然强大但是 ...
- hdu 2041:超级楼梯(水题,递归)
超级楼梯 Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepted Su ...
- Codeforces Round #367 (Div. 2)---水题 | dp | 01字典树
A.Beru-taxi 水题:有一个人站在(sx,sy)的位置,有n辆出租车,正向这个人匀速赶来,每个出租车的位置是(xi, yi) 速度是 Vi;求人最少需要等的时间: 单间循环即可: #inclu ...
- POJ 3176 Cow Bowling (水题DP)
题意:给定一个金字塔,第 i 行有 i 个数,从最上面走下来,只能相邻的层数,问你最大的和. 析:真是水题,学过DP的都会,就不说了. 代码如下: #include <cstdio> #i ...
- URAL 1136 Parliament 二叉树水题 BST后序遍历建树
二叉树水题,特别是昨天刚做完二叉树用中序后序建树,现在来做这个很快的. 跟昨天那题差不多,BST后序遍历的特型,找到最后那个数就是根,向前找,比它小的那块就是他的左儿子,比它大的那块就是右儿子,然后递 ...
- BZOJ USACO 银组 水题集锦
最近刷银组刷得好欢快,好像都是水题,在这里吧他们都记录一下吧(都是水题大家一定是道道都虐的把= =)几道比较神奇的题到时再列出来单独讲一下吧= =(其实我会说是BZOJ蹦了无聊再来写的么 = =) [ ...
- POJ 3984 - 迷宫问题 - [BFS水题]
题目链接:http://poj.org/problem?id=3984 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, ...
随机推荐
- 【温故而知新】HTTP 报文
HTTP 报文是在 HTTP 应用程序之间发送的数据块.这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义. 报文流 报文在客户端.服务器和代理之间的流动称为报文流. HTTP 使用 ...
- User Agent 大全
一.基础知识篇: Http Header之User-Agent User Agent中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA.它是一个特殊字符串头 ...
- SQLServer无法删除登录名'***',因为该用户当前正处于登录状态解决方法
问题描述: sqlserver在删除登录名的时候提示删除失败 标题: Microsoft SQL Server Management Studio -------------------------- ...
- web框架。Django--
一,DIY一个web框架 1.1什么是web框架 1.2用socket模拟B-S的服务端 1.3,浏览器端的network查看 1.4,request格式 1.5,response格式 1.6,初识w ...
- 超哥笔记 -- 用户管理、权限设置、进程管理、中文配置、计划任务和yum源配置(5)
一 网卡配置 ifconfig 查询.设置网卡和ip等参数 ifup,ifdown 脚本命令,更简单的方式启动关闭网络 ip 符合指令,直接修改上述功能 网络配置文件: /etc/sysconf ...
- 【Linux基础】mount报错:mount.nfs: Remote I/O error
问题描述:mount 报错:mount.nfs: Remote I/O error 挂载时需要指明版本,由于NFS服务器有多个版本,V2.V3.V4.而且各版本同时运行,因此挂载时需要说明版本号. 由 ...
- idea spring-boot总结
1. 按自己重新配置spring-boot pom点进 mybatis-spring-boot-starter ,在要改的里面 <version>3.4.4</version> ...
- Kafka配置项unclean.leader.election.enable造成consumer出现offset重置现象
消费端出现offset重置为latest, earliest现象,类似log: (org.apache.kafka.clients.consumer.internals.Fetcher.handleF ...
- kernel笔记——库文件与系统调用
库文件 先从我们熟悉的c库入手,理解系统调用(system call).c代码中调用printf函数,经历了以下调用过程: 最终输出的功能由内核中write调用完成,c库封装了系统调用. 对于以下 ...
- 网络流问题 P2763 试题库问题
题目描述 «问题描述: 假设一个试题库中有n道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取m 道题组成试卷.并要求试卷包含指定类型的试题.试设计一个满足要求的组卷算法. ...