題目鏈結
本題可以用線段樹來做.線段樹的每個區間維護的值如下.(1)該區間的第一段豎直放置時,從該區間頭端指向尾端的向量.(2)拼接兩個子區間(如果有子區間的話)時,右兒子需要旋轉的角度.這裡說明一下,當乙個子區間被修改時,如果它是父區間的右兒子,則父區間維護的角度不用變,如果它是父區間的左兒子,則父區間維護的角度需要累加旋轉角度.當然該子區間也需要累加旋轉角度.也就是說當乙個線段被旋轉之後,編號比它大的線段都需要旋轉相同的角度.拼接兩個子區間的公式如下:
x0=x1+(x2*cos(ang)-y2*sin(ang));
y0=y1+(y2*cos(ang)+x2*sin(ang));
其中(x0,y0)是當前區間維護的向量,(x1,y1)是左兒子向量,(x2,y2)是右二子向量,ang是當前區間維護的角度.x1,y1後面的表示式由右兒子向量旋轉得出.
還有注意線段樹維護的是旋轉角度(即改變量),輸入的時候不能直接輸入題目給的資料,得保留上一次的角度,做差之後才能得到旋轉角度.
1 #include 2 #include 3 #include 45using
namespace
std;
6 typedef unsigned long
long
ull;
7 typedef long
long
ll;8 typedef long
double
lb;9
const
int inf_int=0x3f3f3f3f;10
const ll inf_ll=0x3f3f3f3f3f3f3f3f;11
12const
double pi=acos(-1.0
);13
14 typedef struct node;
15 node tree[4*10000
];16
double pre[20000
];17
18void build(int k,int l,int
r)19
26int mid=(l+r)/2
;27 build(2*k+1,l,mid);build(2*k+2,mid+1
,r);
28 tree[k].y=tree[2*k+1].y+tree[2*k+2
].y;29}
3031
void modify(int k,int s,double ang) //
修改函式
3242
43int
main()
4461 cout<63return0;
64 }
POJ 2991 線段樹區間更新
每個葉子節點儲存每個線段的向量。那麼答案就是線段樹區間和。每次操作就是對向量進行旋轉,線段樹的區間更新加上向量旋轉公式搞定。設有向量 x0,y0 逆時針旋轉a度後的向量為 x1,y1 有 x1 x0 cos a y0 sin a y1 x0 sin a y0 cos a include includ...
ACM Poj 2991 計算幾何 線段樹
題目鏈結。此題涉及到區間所有向量的同一角度旋轉,使用普通陣列維護會超時,因此我們使用線段樹維護,乙個節點維護該區間所有向量的和,最後我們的所求結果就是根節點所維護的向量和。關於線段樹講解可以見此部落格。include include define pi acos 1 using namespace ...
POJ 2991 Crane(線段樹 計算幾何)
description 有一台起重機。我們把起重機看作由n條線段依次首尾相接而成。第i條線段的長度是li。最開始,所有的線段都筆直連線,指向上方。現有c條操縱起重機的指令。指令i給出兩個整數si和ai,效果是使線段si和si 1之間的角度變成ao度。其中角度指的是從線段si開始沿逆時針方向旋轉到si...