// 做法: 线段树 + 区间更新 + 简单计算几何
// 开始的时候在“挑战”这本书上看到,完全是懵逼状态,啥也不知道,就记一个向量旋转
// 之后仔细想了想,旋转角统一转换成向量的形式,对某个s旋转angle角度,就是将s后
// 所有的向量旋转angle角度。这样线段树区间更新的意义就出来了。所以线段树维护的
// 就是每段的向量,即x,y坐标值,还有lazy标签,注意的是:题目输入的是将s变成angle
// 所以需要angle-【s现在的角度】,这样才是旋转所需要的角度.
//
//
//
// 好久没刷题了...退步喽,慢慢来慢慢来...欢迎各位大佬指点
#include <cstdio>
#include <cmath>
#include <algorithm>
#define lson(x) (x << 1)
#define rson(x) ((x << 1) | 1)
const int maxn = 10006;
const double PI =acos(-1.0);
double a[maxn];
int deg[maxn];
struct Seg{
double x[maxn << 3];
double y[maxn << 3];
int lazy[maxn << 3];
void build(int rt, int l, int r){
lazy[rt] = 0;
x[rt] = 0;
if (l == r){
scanf("%lf",&y[rt]);
return ;
}
int mid = l + (r - l) / 2;
build(lson(rt), l, mid);
build(rson(rt), mid + 1, r);
push_up(rt);
}
void rolate(int rt,int ang){
double angle = PI / 180 * ang;
double tx = x[rt];
double ty = y[rt];
x[rt] = cos(angle) * tx - sin(angle) * ty;
y[rt] = sin(angle) * tx + cos(angle) * ty;
}
void push_down(int rt){
if (lazy[rt]){
rolate(lson(rt),lazy[rt]);
rolate(rson(rt),lazy[rt]);
lazy[lson(rt)] += lazy[rt];
lazy[rson(rt)] += lazy[rt];
lazy[rt] = 0;
}
}
void push_up(int rt){
x[rt] = x[lson(rt)] + x[rson(rt)];
y[rt] = y[lson(rt)] + y[rson(rt)];
}
void update(int rt,int ql,int qr,int L, int R, int a){
if (ql <= L && R <= qr){
lazy[rt] += a;
rolate(rt,a);
return;
}
push_down(rt);
int M = L + (R - L) / 2;
if (ql <= M) update(lson(rt), ql, qr, L, M, a);
if (M < qr) update(rson(rt),ql,qr, M+1, R, a);
push_up(rt);
}
}it;
int main(){
int n,c;
//freopen("1.txt","r",stdin);
int flag = 0;
while(scanf("%d%d",&n,&c)!=EOF){
it.build(1,1,n);
if (flag)
puts("");
for (int i = 1;i <= n;i ++)
deg[i] = 180;
for (int i = 0;i < c;i ++){
int s,ang;
scanf("%d%d",&s,&ang);
int rol = (ang - deg[s] + 360) % 360;
it.update(1,s+1,n,1,n,rol);
deg[s] = ang;
printf("%.2lf %.2lf\n",it.x[1],it.y[1]);
}
flag = 1;
}
return 0;
}
poj 2991 Crane 线段树 + 区间更新
最新推荐文章于 2020-02-15 17:04:04 发布