題目大意:網個圖邊長100,有些格點有半徑為10的圓盤。只能沿著邊和圓盤邊界走,不能進入圓盤。問乙個點到另乙個點的最短路。網格圖大小1e8,圓盤個數1e5。不存在兩個圓盤在同一條橫線或者豎線上。
題解:圓盤看上去只會繞遠路,其實不然,如果想要從(x,y)走到(x+1,y+1)並且(x+1,y)處有乙個圓盤的話,那麼就可以通過那個圓盤節省2r-0.5pi*r的路程。然後除了一些邊界情況(起點到終點內部沒有盤子之類的),就是要這樣得情況盡量多,這個線段樹一下就好了。邊界情況還有若這樣得情況等於|x1-x2+1|或者|y1-y2+1|的時候最後一次是經過乙個半圓的,這個要特判。
#include
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define db double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<#define sp <<" "
#define ln typedef pair<
int,
int> pii;
const
int n=
200010
;const db pi=
acos(-
1.0)
,r=10.0
,l=100.0
;inline
intinn()
struct segment
*rt;pii p[n]
;vector<
int> v;
intbuild
(segment*
&rt,
int l,
int r)
intupdate
(segment*
&rt,
int p,
int v)
intquery
(segment*
&rt,
int s,
int t)
#define rev(y) (y=-y)
intmain()
if(x1==x2||y1==y2)
return
!printf
("%.12lf\n"
,double
(l*(x2-x1+y2-y1)
+(pi-2)
*r*cnt));
if(!cnt)
return
!printf
("%.12lf\n"
,double
(l*(x2-x1+y2-y1)))
; n=cnt,
sort
(p+1
,p+n+1)
,build
(rt,
1,n)
;rep
(i,1
,n) v.
pb(p[i]
.sec)
;sort
(v.begin()
,v.end()
);rep(i,
1,n) p[i]
.sec=
lower_bound
(v.begin()
,v.end()
,p[i]
.sec)
-v.begin()
+1;rep
(i,1
,n) t=
query
(rt,
1,p[i]
.sec)+1
,ans=
max(ans,t)
,update
(rt,p[i]
.sec,t)
; db ans=l*
(x2-x1+y2-y1)
-ans*(2
-0.5
*pi)
*r;if
(x2-x1+
1==ans||y2-y1+
1==ans) ans+
=0.5
*pi*r;
return
!printf
("%.12lf"
,double
(ans));
}
Bzoj5251 線段樹 貪心
bzoj5251 線段樹 貪心 記錄本蒟蒻省選後的第一篇題解 國際慣例的題面 首先這個東西顯然是一棵樹。如果我們把數值排序,並建立這棵樹的dfs序,顯然dfs序上的乙個區間對應數值的乙個區間,且根為數值區間左端點。如果你這樣想,恭喜你能獲得50分,如果記得加了eps會獲得55 60分。因為當數值可以...
HDU 6698 Coins(貪心 線段樹)
題意 現在有n nn組數字,每組數字裡面有兩個數a aa,b bb,你需要從這n組數中取k 1 k 2 n k 1 k 2 n k 1 k 2 n 個數,如果你要從一組數中取數,你只有三種取法 解題心得 include using namespace std typedef long long ll...
監視任務 線段樹以及貪心排序
時間限制 c c 2秒,其他語言4秒 空間限制 c c 131072k,其他語言262144k 64bit io format lld 題目描述 在課餘會接受一些民間的鷹眼類委託,即遠距離的狙擊監視防衛。一共接到了?份委託,這些委託與?個直線排布的監視點相關。第?份委託的內容為 對於區間 中的監視點...