倍增:喷泉 深度解析(洛谷P7167)
洛谷传送门
解析
什么破题
数据范围来看很明显最多到nlogn
首先,对于样例进行一下分析:
我们可以把它转化为一棵树:
每一个根都有对应的权,给你一个结点和加权和,问能爬到哪里
既然是树,自然要找爸爸(滑稽)
可以使用一个priority_queue来找:
for(int i=1;i<=n;i++){scanf("%d%d",&p[i].d,&p[i].c);p[i].id=i;while(!q.empty()){node m=q.top();if(m.d<p[i].d){//比当前这个小的//都出来认爸爸q.pop();p[m.id].father=i;}else break;}q.push((node){p[i].d,p[i].c,0,0,i});}
当然,最后还在队列中的就会无爸可归
孤苦伶仃不可怕,水池是我们共同的家
while(!q.empty()){node m=q.top();q.pop();p[m.id].father=0;}
既然是树,我们想到用倍增算法
用dp[i][j]表示从第i个盘接满(是指水真正经过)2^j个盘后所需的总水量
那么递推式就是:
。。。推不下去了
要想让这题得到递推式,我们需要得到dp[i][j-1]后水接到哪一个盘子了
那么就出现了:
dp结构体
(我都不敢写)
struct node2{int num,id;
}dp[100500][30];
//dp[i][j]num表示从i往下走
//2^j个有效的盘至少存的总水量,id表示到达的盘
那么递推式就是(再来一遍 ):
dp[i][j].num=dp[i][j-1].num +
dp[p[dp[i][j-1].id].father][j-1].num;//因为id
//表示j-1操作后接满的盘,所以得从它的爸爸开始
dp[i][j].id=dp[p[dp[i][j-1].id].father][j-1].id;
关于初始化,显然:
dp[i][0].num=p[i].c;//2^0个就是把自己接满了
dp[i][0].id=i;
然后就是写个倍增啦
scanf("%d%d",&r,&tot);int s=0,res,place=r,dep=p[r].deep;res=qu[p[r].deep];int flag=1;while(res>=0){//printf("res:%d\n",res);if(dep>=mi[res]&&dp[place][res].num + s<tot){s+=dp[place][res].num;place=p[dp[place][res].id].father;dep-=mi[res];}if(dp[place][res].num + s == tot){printf("%d\n",dp[place][res].id);flag=0;break;}res --;}if(flag) printf("%d\n",place);
最后一块拼图也已补齐,让我们
召唤神龙!!
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
#include<vector>
using namespace std;
int n,x;
long long sum[100500]={ };
struct node{int d,c,father,deep,id;bool operator < (const node& oth) const{return d > oth.d;}
}p[100500];
struct node2{int num,id;
}dp[100500][30];
//dp[i][j]num表示从i往下走2^j个有效的盘至少存的总水量,id表示到达的盘
priority_queue<node>q;
int mi[20];
int qu[100500];
void solve(){mi[0]=1;for(int i=1;i<=18;i++){mi[i]=mi[i-1] * 2;}int k=1;for(int i=1;i<=n;i++){if(mi[k]<=i) k++;qu[i]=k-1;}
}
int main(){int flag=1;scanf("%d%d",&n,&x);solve();for(int i=1;i<=n;i++){scanf("%d%d",&p[i].d,&p[i].c);p[i].id=i;while(!q.empty()){node m=q.top();if(m.d<p[i].d){q.pop();p[m.id].father=i;}else break;}q.push((node){p[i].d,p[i].c,0,0,i});}while(!q.empty()){node m=q.top();q.pop();p[m.id].father=0;}for(int i=n;i>=1;i--){if(p[i].father==0) p[i].deep=1;else p[i].deep=p[p[i].father].deep+1;}int k=qu[n];//printf("---------\n");for(int i=1;i<=n;i++){dp[i][0].num=p[i].c;dp[i][0].id=i;//printf("%d:%d\n",i,p[i].father);}//printf("---------\n");for(int j=1;j<=k;j++){for(int i=1;i<=n;i++){if(j>qu[p[i].deep]) continue;dp[i][j].num=dp[i][j-1].num +dp[p[dp[i][j-1].id].father][j-1].num;dp[i][j].id=dp[p[dp[i][j-1].id].father][j-1].id;//printf("%d %d: %d %d %d\n",i,j,dp[i][j].num,//dp[i][j-1].num,dp[dp[i][j-1].id][j-1].num); }}int r,tot;/*printf("---------\n");for(int i=1;i<=n;i++){printf("%d : %d %d %d\n",i,p[i].deep,qu[p[i].deep],dp[i][qu[p[i].deep]].num);printf("\n");}printf("---------\n");*/for(int k=1;k<=x;k++){scanf("%d%d",&r,&tot);int s=0,res,place=r,dep=p[r].deep;res=qu[p[r].deep];int flag=1;while(res>=0){//printf("res:%d\n",res);if(dep>=mi[res]&&dp[place][res].num + s<tot){s+=dp[place][res].num;place=p[dp[place][res].id].father;dep-=mi[res];//printf("%d : %d %d %d\n",r,place,s,res);}if(dp[place][res].num + s == tot){printf("%d\n",dp[place][res].id);flag=0;break;}res --;}if(flag) printf("%d\n",place);}return 0;
}
(无处不在的printf可见我究竟调了多久)
AC快乐!!!
倍增:喷泉 深度解析(洛谷P7167)相关推荐
- [最大生成树Kruskal/倍增LCA] 火车运输 洛谷P1967
题目描述 AA 国有 nn 座城市,编号从 11 到 nn ,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重 ...
- DFS深度搜索——洛谷1605迷宫
最近在学习搜索算法,从入门开始学习,发个blog深入理解一下 题目: #include <bits/stdc++.h> using namespace std; int area[101] ...
- 洛谷P1603,P1597
第6章 字符串与文件操作 文章目录 第6章 字符串与文件操作 L P1603 斯诺登的密码 何为斯诺登事件? 理解题意 1.输入 2.运算排列 3.排列 因此,可得代码 代码 解释 N P1597 语 ...
- LOJ6435 洛谷5465 「PKUSC2018」星际穿越 倍增
题目链接: loj6435 洛谷5465 蒟蒻zyd:这不是大水题吗?看我写个O(nlog2n)O(nlog^2n)O(nlog2n)的诡异ST表卡卡常数跑过去 题目:输出区间距离和 蒟蒻zyd:(笑 ...
- 二叉树——二叉树的深度(洛谷 P4913)
题目选自洛谷P4913 题目描述 给出每个节点的两个儿子节点,建立一棵二叉树(根节点为 1),如果是叶子节点,则输入0 0.建好树后希望知道这棵二叉树的深度.二叉树的深度是指从根节点到叶子结点时,最多 ...
- 洛谷 10月 csp-s 模拟赛 T1,T2解析及代码
洛谷 10月 csp-s 模拟赛 T1,T2解析及代码 T1 Magenta Potion 题目描述 给定一个长为 nnn 的整数序列 aaa,其中所有数的绝对值均大于等于 222.有 qqq 次操作 ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- YBTOJ洛谷P4551:最长异或路径(trie树)
洛谷传送门 文章目录 题目描述 解析 代码 题目描述 解析 本题关键就在于一点: 若把每个点的深度dep[i]定义为从根到节点边权的异或和 那么i到j的路径异或和可以表示为: dep[i] ^ dep ...
- 洛谷OJ上的A+B花(zhuang)式(bi)解法
转眼间快到了8月,一想自己都毕业好久了,很怀念曾经在各大OJ上刷题的时光,今天无意在一个算法群里看到最近有个叫洛谷的oj网站貌似蛮火的,于是注册了一个下进去看一看,顺手打开了A+B problem,然 ...
最新文章
- AI框架外部用户贡献代码
- hadoop mac和linux,How to Install Hadoop? (On Mac OS,Linux or Cygwin on Windows)
- 尴尬!中科院国产编程语言“木兰”引争议:声称完全自主,实则换皮Python?...
- ubuntu安装qt4
- 用于web网页的html文件属于,南开15春学期《Web页面设计》在线作业满分答案
- 春节您“抢票”到手了吗,如果没,请进来看看!
- 贾又福大象鸿蒙,奏乐!继续吹!库里又创记录,射进MVP榜单,众多名记变“库吹“...
- CentOS7 设置防火墙端口
- html中logo不变形,CSS3如何实现LOGO中的文本变形动画
- java 毫秒转换秒_毫秒转换成时分秒 格式:HH:mm:ss Java兑现
- myelicpes2019初次使用设置_实况足球2019球员数据编辑器怎么使用
- 什么是支付系统,一分钟带你了解
- 安装MathType后,不能快捷键复制粘贴
- FPGA-VGA驱动Color Bar显示
- 翟菜花:中粮我买网,十年未出线
- JS 正则表达式 数字和小数点 非负数 保留两位小数点
- pymo闪退android7.0,PYMO引擎
- vue的axios两种写法(不知道对不对,仅供参考)
- 为什么会有大端/小端之分?(众说纷纭)
- 埃尔米特插值c语言编程,131张艳-埃尔米特(Hermite)插值逼近的C语言程序.doc
热门文章
- html表格在页面间距,在CSS中设置单元格和单元格间距?
- java利用模板发送邮件_使用JavaMail实现发送模板邮件以及保存到发件箱
- abb限位开关已打开drv1_广告雕刻机限位开关触发
- c语言宏高级用法,C语言宏高级用法 [总结]
- skype linux 安装,Ubuntu 12.04 AMD64 安装 Skype
- php年月日滚动选择,Unity3d—做一个年月日选择器(Scroll Rect拖动效果优化)— 无限滚动 + 锁定元素...
- 在python中strip_python中strip()函数怎么用?
- python数据字符_python数据清洗系列之字符串处理详解
- java的编译器怎么出来_怎样掌握ava编译器的使用,教程在这里,如何进行Java初级学习...
- mysql函数保留小数_MySql自定义函数-关于保留小数位的特殊需求