zoukankan      html  css  js  c++  java
  • hdu 4578 Transformation(线段树)

    Transformation

    Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)
    Total Submission(s): 3084    Accepted Submission(s): 749


    Problem Description
    Yuanfang is puzzled with the question below:
    There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
    Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.
    Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.
    Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.
    Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
    Yuanfang has no idea of how to do it. So he wants to ask you to help him.
     
    Input
    There are no more than 10 test cases.
    For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
    Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
    The input ends with 0 0.
     
    Output
    For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
     
    Sample Input
    5 5
    3 3 5 7
    1 2 4 4
    4 1 5 2
    2 2 5 8
    4 3 5 3
    0 0
     
    Sample Output
    307
    7489
     
     
    写得比较恶心。。因为 p <= 3 , 所以处理好3个sum值 。
    push_down要写得优美才可以过
    至于,过程中那些 + 与 * 的操作的话只是需要把 n 方公式分解好就可以了。
     
    比如 说 ( c * a + b )^ 3 = (c*a)^3 + 3*(c*a)^2*b + 3*(a*c)*b^2 + b^3 .
        那么平方 , 一次的操作也是这么进行
     
    至于操作3的话就是直接把 操作1跟操作2的lazy清空掉就可以了
     
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <queue>
    using namespace std;
    typedef long long LL ;
    typedef pair<int,int> pii ;
    #define X first
    #define Y second
    #define root 1,n,1
    #define lr rt<<1
    #define rr rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    const int N = 200010;
    const int mod = 10007;
    
    int sum1[N<<2] , sum2[N<<2] , sum3[N<<2] , lazy1[N<<2] , lazy2[N<<2] , lazy3[N<<2];
    int n , m ;
    void build( int l , int r , int rt ) {
        sum1[rt] = sum2[rt] = sum3[rt] = 0 ;
        lazy1[rt] = lazy3[rt] = 0 ;   // add  and clean
        lazy2[rt] = 1 ;                 // muti
        if( l == r ) return ;
        int mid = (l+r)>>1;
        build(lson) , build(rson);
    }
    
    void Up( int rt ) {
        sum1[rt] = ( sum1[lr] + sum1[rr] ) % mod ;
        sum2[rt] = ( sum2[lr] + sum2[rr] ) % mod ;
        sum3[rt] = ( sum3[lr] + sum3[rr] ) % mod ;
    }
    
    void Down( int l , int r , int rt ) {
        if( l == r ) return ;
        int mid = (l+r)>>1;
        if( lazy3[rt] != 0 ) {
            lazy3[lr] = lazy3[rr] = lazy3[rt] ;
            lazy1[lr] = lazy1[rr] = 0 ;
            lazy2[lr] = lazy2[rr] = 1 ;
            sum1[lr] = ( mid - l + 1 ) * lazy3[rt] % mod ;
            sum2[lr] = ( mid - l + 1 ) * lazy3[rt] % mod * lazy3[rt] % mod ;
            sum3[lr] = ( mid - l + 1 ) * lazy3[rt] % mod * lazy3[rt] % mod * lazy3[rt] % mod ;
            sum1[rr] = ( r - mid ) * lazy3[rt] % mod ;
            sum2[rr] = ( r - mid ) * lazy3[rt] % mod * lazy3[rt] % mod ;
            sum3[rr] = ( r - mid ) * lazy3[rt] % mod * lazy3[rt] % mod * lazy3[rt] % mod ;
            lazy3[rt] = 0 ;
        }
        if( lazy1[rt] != 0 || lazy2[rt] != 1 ) {
            lazy1[lr] = ( lazy1[lr] * lazy2[rt] % mod + lazy1[rt] ) % mod ;
            lazy2[lr] = lazy2[lr] * lazy2[rt] % mod ;
            sum3[lr] = ( lazy2[rt] * lazy2[rt] % mod * lazy2[rt] % mod * sum3[lr] % mod
                        + 3 * lazy2[rt] % mod * lazy2[rt] % mod * sum2[lr] % mod * lazy1[rt] % mod +
                        + 3 * lazy2[rt] % mod * sum1[lr] % mod * lazy1[rt] % mod * lazy1[rt] % mod
                        + ( mid - l + 1 ) * lazy1[rt] % mod * lazy1[rt] % mod * lazy1[rt] % mod
                        ) % mod ;
            sum2[lr] = ( lazy2[rt] * lazy2[rt] % mod * sum2[lr] % mod
                        + 2 * lazy1[rt] % mod * lazy2[rt] % mod * sum1[lr] % mod
                        + ( mid - l + 1 ) * lazy1[rt] % mod * lazy1[rt] % mod ) % mod ;
            sum1[lr] = ( sum1[lr] * lazy2[rt] % mod + lazy1[rt]*( mid - l + 1 ) % mod ) % mod;
    
    
            lazy1[rr] = ( lazy1[rr] * lazy2[rt] % mod + lazy1[rt] ) % mod ;
            lazy2[rr] = lazy2[rr] * lazy2[rt] % mod ;
            sum3[rr] = ( lazy2[rt] * lazy2[rt] % mod * lazy2[rt] % mod * sum3[rr] % mod
                        + 3 * lazy2[rt] % mod * lazy2[rt] % mod * sum2[rr] % mod * lazy1[rt] % mod +
                        + 3 * lazy2[rt] % mod * sum1[rr] % mod * lazy1[rt] % mod * lazy1[rt] % mod
                        + ( r - mid  ) * lazy1[rt] % mod * lazy1[rt] % mod * lazy1[rt] % mod
                        ) % mod ;
            sum2[rr] = ( lazy2[rt] * lazy2[rt] % mod * sum2[rr] % mod
                        + 2 * lazy1[rt] % mod * lazy2[rt] % mod * sum1[rr] % mod
                        + ( r - mid ) * lazy1[rt] % mod * lazy1[rt] % mod ) % mod ;
            sum1[rr] = ( sum1[rr] * lazy2[rt] % mod + lazy1[rt]*( r - mid ) % mod ) % mod;
            lazy1[rt] = 0;  lazy2[rt] = 1;
            }
    }
    
    void update( int l , int r , int rt , int L , int R , int c , int op ) {
        if( l == L && r == R ) {                // suppose lazy1 = lazy2 = 0 ; op1
            c %= mod ;
            if( op == 1 ) {
                lazy1[rt] = ( c + lazy1[rt] ) % mod;
                sum3[rt] = ( sum3[rt]
                           + 3 * sum2[rt] % mod * c % mod
                           + 3 * sum1[rt] % mod * c % mod * c % mod
                           + c * c % mod * c % mod * ( r - l + 1 ) % mod
                           ) % mod;
                sum2[rt] = ( sum2[rt]
                            + 2 * sum1[rt] % mod * c % mod
                            + c * c % mod * ( r - l + 1 ) % mod
                            ) % mod ;
                sum1[rt] = ( sum1[rt] + ( r - l + 1 ) * c % mod ) % mod;
            }
            else if( op == 2 ) {
                lazy1[rt] = lazy1[rt] * c % mod ;
                lazy2[rt] = lazy2[rt] * c % mod ;
                sum1[rt] = sum1[rt] * c % mod ;
                sum2[rt] = sum2[rt] * c % mod * c % mod ;
                sum3[rt] = sum3[rt] * c % mod * c % mod * c % mod ;
            }
            else {
                lazy1[rt] = 0  ; lazy2[rt] = 1 ; lazy3[rt] = c % mod ;
                sum1[rt] = (r-l+1) * c % mod ;
                sum2[rt] = (r-l+1) * c % mod * c % mod;
                sum3[rt] = (r-l+1) * c % mod * c % mod *c % mod;
            }
            return ;
        }
        Down(l,r,rt);
        int mid = (l+r)>>1;
        if( R <= mid ) update(lson,L,R,c,op);
        else if( L > mid ) update(rson,L,R,c,op);
        else update(lson,L,mid,c,op),update(rson,mid+1,R,c,op);
        Up(rt);
    }
    
    int query( int l , int r , int rt , int L , int R , int c ) {
        if( l == L && r == R ) {
            if( c == 1 ) return sum1[rt] ;
            else if( c == 2 ) return sum2[rt];
            else return sum3[rt];
        }
        Down(l,r,rt);
        int mid = (l+r)>>1;
        if( R <= mid ) return query(lson,L,R,c);
        else if( L > mid ) return query(rson,L,R,c);
        else return (query(lson,L,mid,c)+query(rson,mid+1,R,c))%mod;
    }
    
    int main()
    {
        #ifdef LOCAL
           freopen("in.txt","r",stdin);
           //freopen("out.txt","w",stdout);
        #endif // LOCAL
        while( ~scanf("%d%d",&n,&m ) ) {
            if( n == 0 && m == 0 ) break ;
            build( root ) ;
            int op , x , y , c ;
            while( m-- ) {
                scanf("%d%d%d%d",&op,&x,&y,&c);
                if( op != 4 ) update(root,x,y,c,op);
                else printf("%d
    ",query(root,x,y,c));
            }
        }
    }
    View Code
     
    only strive for your goal , can you make your dream come true ?
  • 相关阅读:
    怎样理解HTMLCollection接口
    怎样单独遍历NodeList的键、值和键值对
    怎样获取NodeList某位置上的节点
    怎样遍历NodeList对象
    怎样理解NodeList的动态集合与静态集合
    怎样将类似数组的对象转换为数组
    怎样理解 instanceof
    怎样清理当前节点下的所有文本节点
    怎样移除当前节点
    怎样判断一个节点是否相等 / 是否相同
  • 原文地址:https://www.cnblogs.com/hlmark/p/4271330.html
Copyright © 2011-2022 走看看