POJ 2991 线段树+向量旋转

向量 (x,y) 逆时针旋转 θ :

x=xcosθysinθ
y=xsinθ+ycosθ
相对旋转量
语言的坑: printf("%.2lf %.2lf", vx[0], vy[0])导致超时的悲剧

#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

using namespace std;

const double M_PI = acos(-1);

const int MAX_N = 10001;
const int ST_SIZE = (1 << 15) - 1;

int N, C;
int L[MAX_N];

double vx[ST_SIZE], vy[ST_SIZE];
double ang[ST_SIZE];
double prev[MAX_N];

// 初始化线段树,结点编号k,表示区间[l,r)
void init(int k, int l, int r) {
  ang[k] = vx[k] = 0;
  if (l == r - 1) {
    vy[k] = L[l];
  } else {
    int lc = 2 * k + 1, rc = 2 * k + 2;
    int m = (l + r) / 2;
    init(lc, l, m);
    init(rc, m, r);
    vy[k] = vy[lc] + vy[rc];
  }
}

//线段树更新,第s和s+1段角度加a,k结点编号,表示区间[l,r)
void change(int s, double a, int k, int l, int r) {
  if (s < l || r <= s + 1) return;
  int lc = 2 * k + 1, rc = 2 * k + 2;
  int m = (l + r) / 2;
  change(s, a, lc, l, m);
  change(s, a, rc, m, r);
  if (s < m) ang[k] += a;
  double si = sin(ang[k]), co = cos(ang[k]);
  vx[k] = vx[lc] + (vx[rc] * co - vy[rc] * si);
  vy[k] = vy[lc] + (vx[rc] * si + vy[rc] * co);
}

int main() {
  while (scanf("%d %d", &N, &C) != EOF) {
    for (int i = 1; i <= N; i++) scanf("%d", L + i);
    init(0, 1, N + 1);
    for (int i = 1; i < N; i++) prev[i] = M_PI;
    for (int i = 0; i < C; i++) {
      int s, a; scanf("%d %d", &s, &a);
      double b = a * 1.0 / 360 * 2 * M_PI;
      change(s, b - prev[s], 0, 1, N + 1);
      prev[s] = b;
      printf("%.2f %.2f\n", vx[0], vy[0]);
    }
    printf("\n");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值