POJ--2991 Crane(线段树(segment tree))
记录
23:40 2023-5-31
http://poj.org/problem?id=2991
reference:《挑战程序设计竞赛(第2版)》3.3.1 p170
这题是抄的,其实理解了线段树的意思,但是这道题给我绕晕了。果然我是菜鸡。
这几次都没继续把题复制过来了,觉得没多大意义 -,-。
哎,有点淡淡的忧伤,加油吧。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
using namespace std;
#define MAX_N 100000
#define MAX_C 100000
typedef long long ll;
typedef unsigned int uint;
const int INF = 0x3f3f3f3f;
int N, C;
int L[MAX_N];
int S[MAX_N], A[MAX_N];
//线段树维护的数据
double vx[2 * MAX_N + 1], vy[2 * MAX_N + 1]; //各节点的数量
double ang[2 * MAX_N + 1]; //各节点的角度
//保存的当前角度的数组
double prv[MAX_N];
void init(int k, int l, int r) {
ang[k] = vx[k] = 0.0;
if(r - l == 1) {
//叶子
vy[k] = L[l];
} else {
//非叶子节点
int chl = k * 2 + 1, chr = k * 2 + 2;
init(chl, l, (l + r) / 2);
init(chr, (l + r) / 2, r);
vy[k] = vy[chl] + vy[chr];
}
}
//把s和s+1的角度变为a
//v是节点的编号,l,r表示当前节点对应的是[l, r)区间
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, 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]);
}
}
void solve() {
//初始化
init(0, 0, N);
for(int i = 1; i < N; i++) prv[i] = M_PI;
//处理操作
for(int i = 0; i < C; i++) {
int s = S[i];
double a = A[i] / 360.0 * 2 * M_PI;
change(s, a - prv[s], 0, 0, N);
prv[s] = a;
printf("%.2f %.2f\n", vx[0], vy[0]);
}
}
int main() {
while(~scanf("%d%d", &N, &C)) {
for(int i = 0; i < N; i++) {
scanf("%d", &L[i]);
}
for(int i = 0; i < C; i++) {
scanf("%d%d", &S[i], &A[i]);
}
solve();
}
}