NOIP2012 开车旅行 倍增与模拟结合后的调试神题
来源:互联网 发布:javascript知识点总结 编辑:程序博客网 时间:2024/05/06 06:58
Problem
偷个懒一定不会被发现的
题外话
话说上午才考完令人发指的[真·NOIp膜你赛],然后整个人都不好了,而且这道题目还是从昨天晚上调一直调到今天下午才A的,然而dalao们都是1A。尤其是中间在调试的时候,内心已经爆炸了。
Solution
其实我觉得当年NOIP出这道题还是比较良心的,暴力分有70分,也就是说单纯去模拟就有70分诶,所以打暴力的性价比是很高的!尤其在考试的时候,我肯定不会优先打这道题的正解,除非你有像 @kb 一样深厚的功力。
很明显,如果打单纯的模拟是拿不了满分的,但是看看数据范围,我们会发现只需要一个log级别的优化就可以A了,那么很容易想到用倍增进行优化,令两天为一轮,那么按照轮次来进行倍增,于是就可以预处理出走
Code
#include <algorithm>#include <iostream>#include <cstdio>using namespace std;typedef long long ll;const int maxn=100010;struct data{ int l,r,h,id; bool operator < (const data &x)const {return h<x.h;}}c[maxn];ll x;int n,m,da,db,l,r,t,ans;double minx=0x3f3f3f3f;int p[maxn],na[maxn],nb[maxn],a[maxn],b[maxn],f[maxn][21],disa[maxn][21],disb[maxn][21];int abs(int x){return x<0?-x:x;}void init(int now){ int l=c[p[now]].l,r=c[p[now]].r; if(!r||(l&&c[p[now]].h-c[l].h<=c[r].h-c[p[now]].h))//the left point is near { nb[now]=c[l].id; int ll=c[l].l; if(!r||(ll&&c[p[now]].h-c[ll].h<=c[r].h-c[p[now]].h)) na[now]=c[ll].id; else na[now]=c[r].id; } else { nb[now]=c[r].id; int rr=c[r].r; if(!rr||(l&&c[p[now]].h-c[l].h<=c[rr].h-c[p[now]].h)) na[now]=c[l].id; else na[now]=c[rr].id; } if(l) c[l].r=r; if(r) c[r].l=l;}void prepare(){ for(int j=1;j<=20;j++)//请注意循环次序! for(int i=1;i<=n;i++) { f[i][j]=f[f[i][j-1]][j-1]; disa[i][j]=disa[i][j-1]+disa[f[i][j-1]][j-1]; disb[i][j]=disb[i][j-1]+disb[f[i][j-1]][j-1]; }}void get(ll x,int p){ da=db=0; for(int i=20;i>=0;i--) if(f[p][i]&&(ll)(da+db+disa[p][i]+disb[p][i])<=x)//为了以防万一 { da+=disa[p][i]; db+=disb[p][i]; p=f[p][i]; } if(na[p]&&da+db+disa[p][0]<=x) da+=disa[p][0];//特判a单独走的情况}int main(){ freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&c[i].h); c[i].id=i; } sort(c+1,c+n+1); for(int i=1;i<=n;i++) { p[c[i].id]=i;//可以说类似于一个离散化吧 c[i].l=i-1;c[i].r=i+1; } c[1].l=c[n].r=0; for(int i=1;i<=n;i++) init(i); for(int i=1;i<=n;i++) { f[i][0]=nb[na[i]]; disa[i][0]=abs(c[p[i]].h-c[p[na[i]]].h); disb[i][0]=abs(c[p[f[i][0]]].h-c[p[na[i]]].h); } prepare(); scanf("%lld%d",&x,&m); for(int i=1;i<=n;i++) { get(x,i); if(db&&da*1.0/db<minx) { minx=da*1.0/db; ans=i; } } printf("%d\n",ans); for(int i=1;i<=m;i++) { scanf("%d%lld",&t,&x); get(x,t); printf("%d %d",da,db); if(i!=m)//可能是因为我脸黑,被洛谷判了too many lines才加的 printf("\n"); } return 0;}
阅读全文
0 0
- NOIP2012 开车旅行 倍增与模拟结合后的调试神题
- NOIP2012 开车旅行 (倍增)
- NOIP2012 开车旅行 【倍增】
- noip2012 开车旅行 set+倍增
- NOIP2012 开车旅行:SET+倍增
- 【vijos1780】【NOIP2012】开车旅行 倍增
- NOIP2012 开车旅行 (倍增)
- noip2012 开车旅行 (倍增处理)
- 【倍增】【set】[NOIP2012] codevs1199 开车旅行
- NOIP2012 开车旅行 [Splay] [ST倍增]
- NOIP2012 T3开车旅行 set+倍增
- 【NOIP2012】开车旅行
- NOIP2012 开车旅行
- NOIP2012 D1T3 开车旅行
- 【NOIP2012】Day1T3 开车旅行
- NOIP2012 开车旅行
- NOIP2012开车旅行
- NOIp2012开车旅行
- 前端学习第七弹:固定位置的导航
- POJ 3140 Contestants Division——树形dp
- vue 非父子组件通信
- Tesseract-OCR识别中文与训练字库实例
- UIScrollView代理方法之一
- NOIP2012 开车旅行 倍增与模拟结合后的调试神题
- 11.Spark SQL:内置函数以及每日uv
- 列主元高斯消元法 C++
- Builder(建造者)模式
- 想知道账号被封的感觉么?
- Java 使用NotePad++DIY一个IDE
- TopShelf+Quartz.net实现window定时调度服务
- 静态方法详解 静态类 静态属性的对比和具体应用
- Unity Shader常见指令和标签