poj 2991 Crane 线段树 + 区间更新

// 做法: 线段树 + 区间更新 + 简单计算几何


// 开始的时候在“挑战”这本书上看到,完全是懵逼状态,啥也不知道,就记一个向量旋转
// 之后仔细想了想,旋转角统一转换成向量的形式,对某个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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值