思路
两个数组,一个记录拉伸的数组,一个记录旋转角度的数组
部分变化,想到前缀和 从某点到另一点,只需看起止变化,从初态到末态共拉伸多少倍,旋转多少度
C++ 代码
#include <iostream>
#include <math.h>
using namespace std;
const int N = 1e5 + 10;
int I[N], i, j, n , m;//I记录的是操作码,即1或2
double op[N], x, y, nx, ny, len[N], ten[N];//op记录的是操作因数
//len拉伸倍数,ten即旋转角度
int main() {
scanf("%d%d", &n, &m);
len[0] = 1;//拉伸长度是乘法前缀积,初始不能为零
for (int k = 1; k <= n; k ++) {
scanf("%d%lf", &I[k], &op[k]);
if (I[k] == 1) {
len[k] = len[k - 1] * op[k];
ten[k] = ten[k - 1];
}//角度没变化,但为了能够一一对应,ten数组扩大一个原数值
else {
len[k] = len[k - 1];
ten[k] = ten[k - 1] + op[k];
}//同理
}
while (m --) {
scanf("%d%d%lf%lf", &i, &j, &x, &y);
x *= len[j] / len[i - 1];
y *= len[j] / len[i - 1];
nx = x;
ny = y;
x = nx * cos(ten[j] - ten[i - 1]) - ny * sin(ten[j] - ten[i - 1]);
y = nx * sin(ten[j] - ten[i - 1]) + ny * cos(ten[j] - ten[i - 1]);
printf("%.3lf %.3lf\n", x, y);
}
return 0;
}