zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4944890.html
Copyright © 2011-2022 走看看