bzoj-2259 新型计算机
来源:互联网 发布:足彩分析软件 编辑:程序博客网 时间:2024/05/02 04:45
题意:
给出一个长度为n的非负序列,将一个元素a修改为A的的代价是|a-A|;
求最小的代价使序列合法 (合法的概念参照原题);
1<=n<=1000000;
题解:
这道题据说要卡O(nlogn),然而我依然选择用O(n*玄学)的算法AC了此题[滑稽];
我们可以很容易的得到一个O(n^2)的算法;
设f[i]为从i开始到序列末尾使序列合法所花费的最小代价,A[i]为i+a[i]+1;
转移即为f[i]=min(f[j]+abs(j-A[i]));
暴力转移是O(n^2),这里我们也可以用线段树优化成O(nlogn);
但是线段树的常数太大了,哪怕是ZKW也会比O(n)慢不知道哪里去了(虽说BZ已经可A了);
我们考虑将转移方程中的abs分情况讨论,那么就是以A[i]为分界的两段方程;
而这两个方程一个可以用单调栈优化,另一个其实可以O(1)出解 (我写的比较凌乱所以都单调栈了= =);
单调栈上可以利用二分找到分界点,比线段树常数要小;
除此以外,实际上我们考虑每一个元素在单调栈中是被谁干掉的,维护这样一个并查集;
这个并查集指向的元素其实就是我们要找的决策点了;
时间复杂度似乎是玄学?不过真的比二分快那么一点。。。
代码:
#include<cctype>#include<stdio.h>#include<string.h>#include<algorithm>#define N 1000100#define LEN 1<<16using namespace std;typedef long long ll;ll f[N];int a[N];int rt1[N],rt2[N];int st1[N],st2[N],top1,top2;char getc(){ static char *S,*T,buf[LEN]; if(S==T) { T=(S=buf)+fread(buf,1,LEN,stdin); if(S==T) return EOF; } return *S++;}int read(){ static char ch; static int D; while(!isdigit(ch=getc())); for(D=ch-'0';isdigit(ch=getc());) D=D*10+ch-'0'; return D;}int find1(int x){ return rt1[x]==x?x:rt1[x]=find1(rt1[x]);}int find2(int x){ return rt2[x]==x?x:rt2[x]=find2(rt2[x]);}int main(){ int n,m,i,j,k,l,r; ll A; n=read(); for(i=1;i<=n;i++) a[i]=read(); memset(f,0x3f,sizeof(f)); f[n+1]=0; st1[top1=1]=n+1; st2[top2=1]=n+1; rt1[n+1]=rt2[n+1]=n+1; for(i=n;i>=1;i--) { rt1[i]=i; rt2[i]=i; A=(ll)a[i]+i+1; if(A<=n+1) l=find1(A),r=find2(A); else l=0,r=st2[1]; f[i]=min(f[l]+l-A,f[r]-r+A); if(f[i]+i<f[st1[top1]]+st1[top1]) st1[++top1]=i; else rt1[i]=st1[top1]; while(top2&&f[i]-i<=f[st2[top2]]-st2[top2]) { rt2[st2[top2]]=i; top2--; } st2[++top2]=i; } printf("%lld\n",f[1]); fclose(stdin); fclose(stdout); return 0;}
0 0
- bzoj-2259 新型计算机
- BZOJ 2259: [Oibh]新型计算机 heap+dijkstra
- bzoj 2259: [Oibh]新型计算机 (最短路)
- 【BZOJ】【P2259】【Oibh】【新型计算机】【题解】【最短路】
- 新型计算机
- 新型计算机
- 【动态规划】新型计算机
- 新型光学装置为超级计算机提速
- 新型生物计算机:分子编程活细胞执行命令
- 【动态规划】新型计算机 computer.pas/c/cpp
- 我研出新型DNA逻辑门 奠定发展DNA计算机基础
- 新型科技
- 新型BT软件雏形
- 发布新型报表工具
- 新型万能登录密码
- 可爱新型素材
- 新型英语学习
- 新型炫酷方法
- Java:String和Date、Timestamp之间的转换
- 三层架构实战篇—系统登录实例
- 三层架构(我的理解及详细分析)
- 获取android应用或apk的md5指纹方法
- 什么是用户画像?金融行业大数据用户画像实践 [
- bzoj-2259 新型计算机
- 关于eclipse安装adt的 Android Development Tools报错
- Ubuntu下添加开机启动脚本
- ubuntu proxy setting
- asp.net三层架构详解
- 盘点大佬们的第一份工作,你和雷军差了 16 年的坚持!
- 指针的用法
- POJ1811-Prime Test-素数测试+Pollard rho因数分解
- Spritekit游戏开发之SKSpriteNode(精灵)一