題意:
直角座標系上有N條相連線段(序號分別爲1,2,3...N)
最底層線段的起點爲原點
每條線段的初始放置狀態平行於y軸方向
輸入每個線段的長度,以及對序號i線段進行的操作角度a
a的含義爲使i與i+1之間角度爲a
輸出進行給定操作後線段端點的座標。
思路:
每次對序號i轉動改變的是編號爲 1到i 以及 i+1到N兩個線段集合的位置關係,需要對兩者狀態進行高效的動態維護。
提取出集合中需要維護的參數並列出關係式即可寫出對應的線段樹算法。
#include <stdio.h>
#include <math.h>
#define MAX_N 10010
#define MAX_C 10010
#define ST_SIZE ((1 << 15) - 1)
#define M_PI 3.1415926
int N, C;
int L[MAX_N];
int S[MAX_C], A[MAX_N];
double vx[ST_SIZE], vy[ST_SIZE]; // position for node
double ang[ST_SIZE];
double prv[MAX_N];
void init(int now, int l, int r)
{
ang[now] = vx[now] = 0.0;
if(r - l == 1)
vy[now] = L[l];
else
{
int chl = 2*now + 1, chr = 2*now + 2;
int mid = (l+r)/2;
init(chl, l, mid);
init(chr, mid, r);
vy[now] = vy[chl]+vy[chr];
}
}
void change(int s, double a, int v, int l, int r)
{
if(s<=l)
return;
else if(s < r)
{
int chl = v*2+1;
int chr = v*2+2;
int m = (l + r)/2;
change(s, a, chl, l, m);
change(s, a, chr, m, r);
if(s <= m)
ang[v] += a;
double s = sin(ang[v]), c = cos(ang[v]);
vx[v] = vx[chl] + (c*vx[chr] - s*vy[chr]);
vy[v] = vy[chl] + (s*vx[chr] + c*vy[chr]);
}
}
int main()
{
int first = 0;
while(scanf("%d %d", &N, &C) == 2)
{
if(first)
printf("\n");
else
first = 1;
for (int i = 0; i < N; ++i)
{
scanf("%d", &L[i]);
prv[i] = M_PI;
}
init(0, 0, N);
for (int i = 0; i < C; ++i)
{
int s;
double a;
scanf("%d %lf", &s, &a);
a = a/360.0 * 2 * M_PI;
change(s, a - prv[s], 0, 0, N);
prv[s] = a;
printf("%.2f %.2f\n", vx[0], vy[0]);
}
}
}
結果是WA,可能哪些細節沒有處理好