POJ 2991 Crane(线段树)

很自然会想到是线段树,需要考虑维护什么信息。

我们需要的答案是从原点到末端的坐标,这个信息可以看出是多个向量相加,所以我们在子区间维护左端点到右端点的一个向量。

因为角度会发生改变,那么再维护一个左右区间之间的角度。那么父节点的向量就等于左孩子的向量加上右孩子旋转以后的向量。

对于修改si和si+1之间的角度,对于以上的信息,相当于si+1以后所有角度都增加了。因此只要修改增量就好了。

此外,线段树最大深度的科学估计方法:max_deep = ceil(log2(maxn))+1),而且2^(max_deep ) ≤4*maxn,是一个更紧的上界,对于主席树也适用。

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long ll;

#define para int o = 1, int l = 0,int r = n-1
#define lo (o<<1)
#define ro (o<<1|1)
#define TEMPvar int mid = (l+r)>>1, lc = lo, rc = ro;
#define lsn lc, l, mid
#define rsn rc, mid+1, r

const int maxn = 1e4+5, ST_SIZE = 1<<15;//((int)ceil(log2(maxn))+1);//4*N , 0base -1
const double PI = acos(-1);
double rad[ST_SIZE];
double vx[ST_SIZE], vy[ST_SIZE];
int L[maxn];
int n;
double prv[maxn];

void build(para)
{
    rad[o] = vx[o] = 0;
    if(r == l){
        vy[o] = L[l];
    }
    else {
        TEMPvar
        build(lsn);
        build(rsn);
        vy[o] = vy[lc] + vy[rc];
    }
}

int qs;
double qDrad;
void update(para)
{
    if(l < r){
        TEMPvar
        if(qs<=mid) {
            update(lsn);
            rad[o] += qDrad;
        }
        else update(rsn);

        double s = sin(rad[o]), c = cos(rad[o]);
        vx[o] = vx[lc] + c*vx[rc] - s*vy[rc];
        vy[o] = vy[lc] + s*vx[rc] + c*vy[rc];
    }
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int C;
    bool firstCase = true;
    while(~scanf("%d%d",&n,&C)){
        if(!firstCase) puts("");
        else firstCase = false;
        for(int i = 0; i < n; i++) scanf("%d", L+i);
        fill(prv,prv+n-1,PI);
        build();
        while(C--){
            double ang;
            scanf("%d %lf", &qs, &ang);
            ang = ang/180*PI;
            qDrad = ang-prv[--qs];
            update();
            prv[qs] = ang;
            printf("%.2f %.2f
", vx[1], vy[1]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4944890.html