[bzoj2259][Oibh]新型计算机_Dijkstra
新型計(jì)算機(jī) bzoj-2259 Oibh
題目大意:給定一個(gè)n個(gè)數(shù)的數(shù)列,第i個(gè)數(shù)為a[i],更改第i個(gè)數(shù)至x的代價(jià)為|x-a[i]|。求最小代價(jià),使得:讀入一個(gè)數(shù)s1后,向后連著讀s1個(gè)數(shù),然后如s2,再向后讀s2個(gè)數(shù)。保證最后恰好讀到第n個(gè)數(shù)。
注釋:$1\le n\le 10^6$
想法:又開(kāi)始了... ...在那里一頓dp...
結(jié)果又是一個(gè)圖論題.. ..這場(chǎng)面好熟悉
我們直接從第i個(gè)數(shù)像第i+a[i]連一條邊權(quán)為0的邊。然后這時(shí)我們思考暴力怎么做?暴力的話從i+a[i]開(kāi)始像左右依次連邊權(quán)為1,2,3...的邊,然后Dijkstra即可,時(shí)空復(fù)雜度均為$O(n^2)$。如何優(yōu)化這一過(guò)程?我們思考:其實(shí)這中的有些邊是沒(méi)有用的,我們只需要將相鄰兩個(gè)點(diǎn)之間連一條邊權(quán)為1的邊即可。然后堆優(yōu)化Dij,時(shí)間復(fù)雜度為O(nlogn)。
正確性:我們發(fā)現(xiàn):絕對(duì)值函數(shù)f(x)=|x|是一個(gè)偶函數(shù),而且是一個(gè)線性偶函數(shù),所以這東西支持在符號(hào)相同的情況下加減,在符號(hào)不同的情況下可以直接通過(guò)我們連的邊退回去,證畢。
最后,附上丑陋的代碼... ...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 1000010
#define mp make_pair
using namespace std;
priority_queue<pair<int,int> > pq;
int to[N<<2],nxt[N<<2],val[N<<2],head[N],tot;
int dis[N]; bool lv[N],rv[N],vis[N];
inline void add(int x,int y,int z)
{to[++tot]=y;val[tot]=z;nxt[tot]=head[x];head[x]=tot;
}
int main()
{int n; cin >> n ;for(int u,i=1;i<=n;i++){scanf("%d",&u);if(i+u>n) add(i,n+1,i+u-n);else add(i,i+u+1,0);for(int j=i+1;j<=i+u+1&&j<=n&&!lv[j];j++) lv[j]=1,add(j,j-1,1);for(int j=i+u+1;j<=n&&!rv[j];j++) rv[j]=1,add(j,j+1,1);}memset(dis,0x3f,sizeof(dis));pq.push(mp(0,1)),dis[1]=0;while(!pq.empty()){int u=pq.top().second; pq.pop();if(vis[u]) continue;vis[u]=1;for(int i=head[u];i;i=nxt[i])if(dis[to[i]]>dis[u]+val[i])dis[to[i]]=dis[u]+val[i],pq.push(mp(-dis[to[i]],to[i]));}printf("%d\n",dis[n+1]);return 0;
}
小結(jié):圖論真tm難... ...
轉(zhuǎn)載于:https://www.cnblogs.com/ShuraK/p/9374987.html
總結(jié)
以上是生活随笔為你收集整理的[bzoj2259][Oibh]新型计算机_Dijkstra的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 求婉君歌词!
- 下一篇: 前端开发工程师面试题之综合篇