题目链接
有N条线段,初始状态全部竖直向上,在每条线段的最上方有一个可以旋转的关节点。
当一个关节点旋转时,它上面所有的线段都会跟着旋转。
每次旋转后,求最上面一个关节点的坐标
区间修改。每个节点 存一个向量,从起始点指向结束点,还要存一个要转到既定位置,要转多少角度。
题目给的是角度,我们要换成 rad 形式。
题目给的角度并不是我们在线段树种存的角度。
求一个向量(x0,y0)逆时针旋转B度后的向量有一个公式:
x1= x0 * cosB - y0 * sinB
y1 = x0 * sinB + y0 * cosB
顺时针就把-B代入:
x1= x0 * cosB + y0 * sinB
y1 = -x0 * sinB + y0 * cosB
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 2e4 + 10;
const double PI = acos(-1.0);
int n,m,x,t,y,pre[N],z;
int yy[N],an;
struct node {
int a,b,l,r,ang;
double vx,vy;
int cal_mid(){
return (a + b) / 2;
}
}f[N*2];
double get(int x){
return x * PI / 180; //转化成弧度制。
}
void Rotate(int p, int d){
double rad = get(d);
double xx = f[p].vx, yy = f[p].vy;
f[p].vx = xx * cos(rad) - yy * sin(rad); //套用公式。
f[p].vy = xx * sin(rad) + yy * cos(rad);
return;
}
void push_down(int p){
if (f[p].ang == 0) return;
f[f[p].l].ang += f[p].ang;
f[f[p].r].ang += f[p].ang;
Rotate(f[p].l,f[p].ang);
Rotate(f[p].r,f[p].ang);
f[p].ang = 0;
return;
}
void build(int p, int a, int b){
f[p].a = a; f[p].b = b;
f[p].vx =f[p].ang = 0;
if (a + 1 == b){
f[p].vy = yy[a];
return;
}
int m = f[p].cal_mid();
t++; f[p].l = t; build(t,a,m);
t++; f[p].r = t; build(t,m,b);
f[p].vy = f[f[p].l].vy + f[f[p].r].vy;
return;
}
void push_up(int p){
f[p].vx = f[f[p].l].vx + f[f[p].r].vx;
f[p].vy = f[f[p].l].vy + f[f[p].r].vy;
return;
}
void Insert(int p){
if (x <= f[p].a && y >= f[p].b - 1){
f[p].ang += z;
Rotate(p,z);
return;
}
push_down(p);
int m = f[p].cal_mid();
if (x < m) Insert(f[p].l);
if (y >= m) Insert(f[p].r);
push_up(p);
return;
}
int main() {
int num = 0;
while(scanf("%d%d",&n,&m) == 2){
if (num != 0) printf("\n");
num++;
for (int i = 1; i <= n; i++)
pre[i] = 180; //当前线段和前一个线段之间的角度
for (int i = 1; i <= n; i++)
scanf("%d",&yy[i]);
t = 1;
build(1,1,n+1);
for (int i = 1; i <= m; i++){
scanf("%d%d",&x,&an);
x++; //我们要改的是 读入的x 下一条线段。
y = n;
z = an - pre[x]; // 要转多少角度。
pre[x] = an;
Insert(1);
printf("%.2lf %.2lf\n",f[1].vx,f[1].vy);
}
}
return 0;
}
/*
10 10
2 8 5 1 10 5 9 9 3 5
3 305
7 241
6 241
9 115
1 147
7 351
1 302
8 292
6 141
6 278
-34.40 -9.09
-18.70 -16.25
3.48 -9.77
-0.95 -12.81
-8.86 -9.91
-1.03 13.08
-3.74 -8.48
4.05 -16.70
-1.83 -10.51
7.32 -15.38
*/