题意:给出n个杆子的长度a[i],初始杆子的头在(0,0),尾部在(0,a[1]),第二个头在(0,a[1]),尾在(a[1],a[2]),之后都保持竖直。连续两个杆子通过一个节点连接,每个节点可以旋转一定的角度,有操作s a表示将第s和s+1的杆子之间的节点旋转,让两个杆子角度相差a°,输出每次操作后第n个节点的位置。
题解:因为旋转后s+1的杆子到最后第n个杆子的位置都会改变,但除了第s和s+1杆子的相对角度变化了,其他杆子之间相对角度不变,第s+1杆子的旋转看做向量的旋转,每个杆子的向量旋转和就是最后一个杆子的终点,线段树查询操作得到向量旋转的角度,后面的杆子旋转后的向量用区间更新。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 10005;
const double PI = acos(-1);
struct Tree {
double x, y;
int flag, ang;
}tree[N << 2];
int n, c, a[N];
void Rotate(int k, int angle) {
double rad = angle * PI / 180.0;
double x1 = tree[k].x;
double y1 = tree[k].y;
tree[k].x = x1 * cos(rad) - y1 * sin(rad);
tree[k].y = x1 * sin(rad) + y1 * cos(rad);
tree[k].ang = (tree[k].ang + angle) % 360;
tree[k].flag = (tree[k].flag + angle) % 360;
}
void pushdown(int k) {
if (tree[k].flag) {
Rotate(k * 2, tree[k].flag);
Rotate(k * 2 + 1, tree[k].flag);
tree[k].flag = 0;
}
}
void pushup(int k) {
tree[k].x = tree[k * 2].x + tree[k * 2 + 1].x;
tree[k].y = tree[k * 2].y + tree[k * 2 + 1].y;
}
int query(int k, int left, int right, int x) {
if (left == right)
return tree[k].ang;
pushdown(k);
int mid = (left + right) / 2, ang;
if (x <= mid)
ang = query(k * 2, left, mid, x);
else
ang = query(k * 2 + 1, mid + 1, right, x);
pushup(k);
return ang;
}
void modify(int k, int left, int right, int l, int r, int x) {
if (l <= left && right <= r) {
Rotate(k, x);
return;
}
pushdown(k);
int mid = (left + right) / 2;
if (l <= mid)
modify(k * 2, left, mid, l, r, x);
if (r > mid)
modify(k * 2 + 1, mid + 1, right, l, r, x);
pushup(k);
}
void build(int k, int left, int right) {
tree[k].flag = tree[k].ang = 0;
if (left == right) {
tree[k].x = 0;
tree[k].y = a[left];
return;
}
int mid = (left + right) / 2;
build(k * 2, left, mid);
build(k * 2 + 1, mid + 1, right);
pushup(k);
}
int main() {
int t = 0;
while (scanf("%d%d", &n, &c) == 2) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
if (!t)
t = 1;
else
printf("\n");
build(1, 1, n);
int s, angle;
while (c--) {
scanf("%d%d", &s, &angle);
int ang = query(1, 1, n, s) + 180 - query(1, 1, n, s + 1) + angle;
modify(1, 1, n, s + 1, n, ang);
printf("%.2f %.2f\n", tree[1].x, tree[1].y);
}
}
return 0;
}