Crane POJ 2991 線段樹 計算幾何

2022-09-01 08:18:10 字數 1469 閱讀 3174

題目鏈結

本題可以用線段樹來做.線段樹的每個區間維護的值如下.(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 4

5using

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...