POJ 2991 Crane(線段樹 計算幾何)

2021-07-03 18:17:19 字數 1729 閱讀 8901

description

有一台起重機。我們把起重機看作由n條線段依次首尾相接而成。第i條線段的長度是li。最開始,所有的線段都筆直連線,指向上方。現有c條操縱起重機的指令。指令i給出兩個整數si和ai,效果是使線段si和si+1之間的角度變成ao度。其中角度指的是從線段si開始沿逆時針方向旋轉到si+1所經過的角度。最開始所有角度都是180度。按順序執行這c條指令。在每條指令執行之後,輸出起重機的前段(第n條線段的端點)的座標。假設起重機的支點座標是(0,0)

input

多組用例,每組用例第一行為兩個整數n和c分別表示起重機的線段數和指令數,第二行為n個整數表示各線段的長度,之後c行每行兩個整數表示指令,以檔案尾結束輸入

output

對於每組用例,輸出執行完一條指令後起重機前段的座標,用空行隔開兩組輸出

sample input

2 1

10 5

1 90

3 2

5 5 5

1 270

2 90

sample output

5.00 10.00

-10.00 5.00

-5.00 10.00

solution

本題用線段樹來解決,每個節點表示一段連續的線段的集合,並且維護下面兩個值

1,把對應的線段集合中的第一條線段轉至垂直方向後,從第一條線段的起點指向最後一條線段的終點的向量

2,(如果該節點有葉子節點)兩個兒子節點對應的部分連線後,右兒子需要轉動的角度

也就是說,如果節點i表示的向量是xi,yi,角度是angi,兩個兒子節點是chl和chr,那麼就有

xi=xchl+(cos(angi)*xchr-sin(angi)*ychr)

yi=ychl+(sin(angi)*xchr+cos(angi)*ychr)

這樣,每次更新便在o(logn)時間內完成,而輸出的值就是根節點對應向量的值

code

#include

#include

#include

#include

using

namespace

std;

#define maxn 10001

const

int st_size=(1

<<15)-1;

int n,c;

int l[maxn];

int s[maxn],a[maxn];

//線段樹所維護的資料

double vx[st_size],vy[st_size];//各節點的向量

double ang[st_size];//各節點的角度

double prv[maxn];//為了查詢角度的變化而儲存當前角度的陣列

void init(int k,int l,int r)//初始化線段樹,k為節點編號,l,r表示當前節點對應的是[l,r)區間

}void change(int s,double a,int v,int l,int r)//把s和s+1的角度變成a,v是節點編號,l,r表示當前節點對應的是[l,r)區間

}int main()

}return

0;}

POJ 2991 Crane(計算幾何 線段樹)

題目位址 題意 你有乙個挖掘機,他的臂由n根小臂組成,最初的時候挖掘機的臂是垂直向上的,然後有n次操作,每次操作告訴你把第a和第a 1根臂之間的角度旋轉為b 不是旋轉角度為b 每次操作之後把最後那個臂的座標輸出 思路 用線段樹去維護每個臂的向量,然後把第a和第a 1個臂之間的角度旋轉為b這個操作就是...

POJ 2991 Crane(區間更新 向量旋轉)

題目大意 n個向量首尾相連,每次操作使某個區間中的所有向量都旋轉同樣的角度。每次操作後都回答最後乙個向量的座標。題目分析 區間維護向量資訊。向量旋 x1 x0 cos t y0 sin t y1 x0 sin t y0 cos t 其中t為旋轉的角度。如下 include include inclu...

POJ 2991 線段樹區間更新

每個葉子節點儲存每個線段的向量。那麼答案就是線段樹區間和。每次操作就是對向量進行旋轉,線段樹的區間更新加上向量旋轉公式搞定。設有向量 x0,y0 逆時針旋轉a度後的向量為 x1,y1 有 x1 x0 cos a y0 sin a y1 x0 sin a y0 cos a include includ...