POJ 2991

題意:

 

直角座標系上有N條相連線段(序號分別爲1,2,3...N

 

最底層線段的起點爲原點

每條線段的初始放置狀態平行於y軸方向

 

輸入每個線段的長度,以及對序號i線段進行的操作角度a

a的含義爲使ii+1之間角度爲a

 

輸出進行給定操作後線段端點的座標。

 

思路:

 

每次對序號i轉動改變的是編號爲 1以及 i+1N兩個線段集合的位置關係,需要對兩者狀態進行高效的動態維護。

 

提取出集合中需要維護的參數並列出關係式即可寫出對應的線段樹算法。


#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,可能哪些細節沒有處理好

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章