hdu題面spa
首先咱們要選一個起點,這個起點應該在第一個區間內,而後再看第二個區間在左邊仍是右邊以便移動,但轉念一想,咱們能夠把起點直接選在前一堆區間的交集上,因而思路就有了——依次把全部區間取交集,若是沒有交集就搞一個新的區間,以後的接着取交集,獲得一堆合併出來的區間。而後就在合併的區間上移動就好。.net
有一個細節要注意。舉個例子,若是如今位置在\(3\),以後的兩個目標區間依次是\([6,7]\)、\([9,10]\),那麼咱們若是通過兩次移動(先1後2)到達第一個區間的左端點\(6\),下一步就要再移動兩次才能到達\(9\),因此第一步不妨用相同的代價(兩次移動)多走點,走到7,那麼第二步到\(9\)就只用移動一次就好。code
比賽時合併區間寫的有問題,WA*7,最後兩題慘淡收場……ip
#include<cstdio> #include<algorithm> int T,n; struct D{ int a,b; }p[1010]; int num; int l,r; int main() { scanf("%d",&T); while(T--) { num=0; scanf("%d%d%d",&n,&l,&r); for(int i=1,a,b;i<n;i++) { scanf("%d%d",&a,&b); if(a>r||b<l) { p[num++]={l,r}; l=a; r=b; } else { l=std::max(l,a); r=std::min(b,r); } if(i==n-1) p[num++]={l,r};//比賽時這句話被我寫到循環外面去了…… } int pos; if(p[0].b<p[1].a) pos=p[0].b; else pos=p[0].a; long long ans=0; for(int i=1;i<num;i++) { if(pos<p[i].a)//向右走 { int delta=p[i].a-pos; pos=p[i].a; ans+=delta>>1; if(delta&1) { ans++; if(i+1<num&&pos+1<=p[i].b&&p[i+1].a>pos) pos++; } } else//向左走 { int delta=pos-p[i].b; pos=p[i].b; ans+=delta>>1; if(delta&1) { ans++; if(i+1<num&&pos-1>=p[i].a&&p[i+1].b<pos) pos--; } } } printf("%lld\n",ans); } return 0; }