BZOJ 3211: 花神游历各国

二次联通门 : BZOJ 3211: 花神游历各国

 

 

 

/*
    BZOJ 3211: 花神游历各国
    
    线段树维护区间和
    
    对于开方操作
    思考一下, 若其为1或0
    则无论其怎样开方值, 都不会再改变 
    
    那么打个标记即可, 
    若当前节点的左儿子和右儿子都小于等于1, 那么就没有再进行下去的必要了
    
    标记依次上传即可 

        和上帝那个题一模一样。。。
*/
#include <cstdio>
#include <cmath>

void read (long long &now)
{
    now = 0;
    register char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

inline long long min (long long a, long long b)
{
    return a < b ? a : b;
}

inline long long max (long long a, long long b)
{
    return a > b ? a : b;
}

struct Segment_Tree_Date
{
    Segment_Tree_Date *Left, *Right;
    
    long long l, r;
    
    long long Mid;
    long long key;
    bool Flandre;
    
    Segment_Tree_Date ()
    {
        Left = NULL;
        Right = NULL;
        key = 0;
        Flandre = false;
    }
};

Segment_Tree_Date *Root;

class Segment_Tree_Type
{
    public :
        
        void Build (Segment_Tree_Date *&now, long long l, long long r)
        {
            now = new Segment_Tree_Date ;
            now->l = l;
            now->r = r;
            if (l == r)
            {
                read (now->key);
                if (now->key <= 1)
                    now->Flandre = true;
                return ;
            }
            now->Mid = l + r >> 1;
            Build (now->Left, l, now->Mid);
            Build (now->Right, now->Mid + 1, r);
            now->key = now->Left->key + now->Right->key;
            now->Flandre = now->Left->Flandre & now->Right->Flandre;
        }
        
        void Change_Section (Segment_Tree_Date *&now, long long l, long long r)
        {
            if (now->l == now->r)
            {
                now->key = (long long)sqrt (now->key);
                if (now->key <= 1)
                    now->Flandre = true;
                return ;
            }
            if (now->Flandre)
                return ;
            if (l <= now->Mid)
                Change_Section (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                Change_Section (now->Right, max (now->Mid + 1, l), r);
            now->key = now->Left->key + now->Right->key;
            now->Flandre = now->Left->Flandre & now->Right->Flandre;
        }
        
        long long Query_Section (Segment_Tree_Date *&now, long long l, long long r)
        {
            if (l <= now->l && now->r <= r)
                return now->key;
            long long res = 0;
            if (l <= now->Mid)
                res += Query_Section (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                res += Query_Section (now->Right, max (now->Mid + 1, l), r);
            return res;
        }
};

Segment_Tree_Type Tree;

long long N;

int main (int argc, char *argv[])
{
    read (N);
    Tree.Build (Root, 1, N); 
    long long x, y, type;
    for (read (N); N--; )
    {
        read (type);
        read (x);
        read (y);
        if (type == 1)
            printf ("%lld\n", Tree.Query_Section (Root, min (x, y), max (x, y)));
        else
            Tree.Change_Section (Root, min (x, y), max (x, y)); 
    }
    return 0;
}

 

posted @ 2017-06-03 17:32  ZlycerQan  阅读(183)  评论(0编辑  收藏  举报