POJ 2991 Crane

二次联通门 : POJ 2991 Crane

/*
    POJ 2991 Crane 
    
    线段树维护向量
    对于每次修改操作
    修改x的角度 
    就是修改x~N区间的所有向量
    
    打个标记记录角度
    
    当前向量的计算式子为
    res为度数 
    x = tree[now].x * cos (res) - tree[now].y * sin (res);
    y = tree[now].x * sin (res) + tree[now].y * cos (res);
    
    注意弧度制与角度值的互换
    
    注意还要记录一下上次该向量的角度, 即angle[i] 
     
    每次修改的角度就是x - angle[pos] x是给定的角, pos是修改的位置 
     
    查询的话就是第一个点的向量。。。
    
    MMP竟然有负角。。。
    我的读入优化没判负数导致WA了半天。。。 
*/
#include <cstdio>
#include <cmath>

#define Max 1000001

inline void read (int &now)
{
    now = 0;
    register char word = getchar ();
    bool temp = false;
    while (word < '0' || word > '9')
    {
        if (word == '-')
            temp = true;
        word = getchar ();
    }
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
    if (temp)
        now = -now;
}

int N, M;

double angle[Max];

class Segment_Tree_Type
{
    
    private :
        
        
        struct Segment_Tree_Date
        {
            int l;
            int r;
            int Mid;
            double x;
            double y;
            double Flandre;
            
        }
        tree[Max];
        
        inline void Rotate (int now, int angle)
        {
            double res = (double)angle * acos (-1.0) / 180.0;
            double x = tree[now].x * cos (res) - tree[now].y * sin (res);
            double y = tree[now].x * sin (res) + tree[now].y * cos (res);
            tree[now].x = x;
            tree[now].y = y;
        }
        
    public :
        
        void Build (int l, int r, int now)
        {
            tree[now].l = l;
            tree[now].r = r;
            tree[now].Flandre = 0;
            if (l == r)
            {
                scanf ("%lf", &tree[now].y);
                tree[now].x = 0;
                tree[now].Flandre = 0;
                return ;
            }
            tree[now].Mid = l + r >> 1;
            Build (l, tree[now].Mid, now << 1);
            Build (tree[now].Mid + 1, r, now << 1 | 1);
            tree[now].x = tree[now << 1].x + tree[now << 1 | 1].x;
            tree[now].y = tree[now << 1].y + tree[now << 1 | 1].y;
        }
    
        void Change_section (int l, int r, int now, int to)
        {
            if (tree[now].l == l && tree[now].r == r)
            {
                tree[now].Flandre += to;
                Rotate (now, to);
                return ;
            }
            if (tree[now].Flandre)
            {
                tree[now << 1].Flandre += tree[now].Flandre;
                tree[now << 1 | 1].Flandre += tree[now].Flandre;
                Rotate ((now << 1), tree[now].Flandre);
                Rotate ((now << 1 | 1), tree[now].Flandre);
                tree[now].Flandre = 0;
            }
            if (r <= tree[now].Mid)
                Change_section (l, r, now << 1, to);
            else if (l > tree[now].Mid)
                Change_section (l, r, now << 1 |1, to);
            else 
            {
                Change_section (l, tree[now].Mid, now << 1, to);
                Change_section (tree[now].Mid + 1, r, now << 1 | 1, to);
            }
            tree[now].x = tree[now << 1].x + tree[now << 1 | 1].x;
            tree[now].y = tree[now << 1].y + tree[now << 1 | 1].y;
        }
        
        inline double Query_x ()
        {
            return tree[1].x;
        }
        
        inline double Query_y ()
        {
            return tree[1].y;
        }
        
        void Prepare ()
        {
            for (int i = 1; i <= Max; i++)
                angle[i] = 180.0;
        }
};

Segment_Tree_Type Tree;


int main (int argc, char *argv[])
{
    int x, y;
    for (; scanf ("%d%d", &N, &M) == 2; )
    {
        Tree.Build (1, N, 1); 
        Tree.Prepare (); 
        for (; M--; )
        {
            read (x);
            read (y);
            Tree.Change_section (x + 1, N, 1, y - angle[x]); 
            printf ("%.2lf %.2lf
", Tree.Query_x (), Tree.Query_y ());
            angle[x] = (double)y;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/6910546.html