hdu4578Transformation 线段树

来源:互联网 发布:同花顺财经软件下载 编辑:程序博客网 时间:2024/06/07 00:14
//长度为n的数组 四个操作
//1 x y  c [x,y]区间的数都加c
//2 x y c [x, y] 区间的数都乘以c
//3 x y c [x ,y] 区间的数都变为c
//4 x y p [x ,y] 求区间的数的p次方的和
//用线段树维护里面的值都相等的区间 ,那么这个区间的所需答案为(r-l+1)*(tree[v].eq)^q
//对于懒惰操作 mul , eq , add的处理是
//对于每次eq操作可以直接操作tree[v].eq = eq ;tree[v].mul = 1 ; tree[v].add = 0;
//而对于mul ,和add的操作每次push_down(v)的时候保证下面一层的所有懒惰情况都是初始情况
//所以对于mul和add操作时就一直往下push_down知道找到一个可以
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 100010 ;
#define left v<<1
#define right v<<1|1
#define mod  10007
struct node
{
    int l ,r , value ;
    int eq , add , mul ;
}tree[maxn<<2];
void build(int l , int r  , int v)
{
    tree[v].l = l ;
    tree[v].r = r ;
    tree[v].add = 0 ; tree[v].mul = 1 ;tree[v].eq = -1 ;
    if(l == r)
    {tree[v].eq = 0 ; return  ;}
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid + 1 , r , right) ;
}
void push_down(int v)
{
    if(tree[v].l == tree[v].r)return ;
    if(tree[v].eq != -1)
    {
        tree[left].eq = tree[right].eq = tree[v].eq ;
        tree[left].add = tree[right].add = 0 ;
        tree[left].mul = tree[right].mul = 1;
        tree[v].eq = -1;
        return  ;
    }
    if(tree[v].mul != 1)
    {
        if(tree[left].eq != -1)
        tree[left].eq = (tree[left].eq*tree[v].mul)%mod ;
        else
        {
            push_down(left) ;
            tree[left].mul = (tree[left].mul*tree[v].mul)%mod ;
        }
        if(tree[right].eq != -1)
        tree[right].eq = (tree[right].eq*tree[v].mul)%mod ;
        else
        {
            push_down(right) ;
            tree[right].mul = (tree[right].mul*tree[v].mul)%mod ;
        }
        tree[v].mul = 1;
    }
    if(tree[v].add)
    {
        if(tree[left].eq != -1)
        tree[left].eq = (tree[left].eq + tree[v].add)%mod ;
        else
        {
            push_down(left) ;
            tree[left].add = (tree[left].add + tree[v].add)%mod ;
        }
        if(tree[right].eq != -1)
        tree[right].eq = (tree[right].eq + tree[v].add)%mod ;
        else
        {
            push_down(right) ;
            tree[right].add = (tree[right].add + tree[v].add)%mod ;
        }
        tree[v].add = 0 ;
    }
}
void update(int l , int r , int v , int op , int c)
{
    if(l <= tree[v].l && tree[v].r <= r)
    {
        if(op == 3)
        {
            tree[v].add = 0 ;tree[v].mul = 1;
            tree[v].eq  = c ;
            return ;
        }
        if(tree[v].eq != -1)
        {
            if(op == 1)tree[v].eq = (tree[v].eq + c)%mod ;
            else tree[v].eq = (tree[v].eq*c)%mod ;
        }
        else
        {
            push_down(v) ;
            if(op == 1)tree[v].add = (tree[v].add + c)%mod ;
            else tree[v].mul = (tree[v].mul*c)%mod ;
        }
        return ;
    }
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(l <= mid)update(l , r ,left , op , c) ;
    if(r > mid)update(l , r , right , op , c) ;
}
int query(int l , int r , int v , int q)
{
    if(tree[v].l >= l && tree[v].r <= r && tree[v].eq != -1)
    {
        int ans = 1;
        for(int i = 1;i <= q;i++)
        ans = (ans * tree[v].eq)%mod ;
        return (ans*((tree[v].r - tree[v].l + 1)%mod))%mod ;
    }
    push_down(v) ;
    int mid = (tree[v].l  + tree[v].r) >> 1 ;
    if(l > mid)return query(l , r , right, q) ;
    else if(r <= mid)return query(l , r ,left ,q) ;
    else return (query(l , mid , left , q) + query(mid + 1 , r , right , q))%mod ;
}
int main()
{
    //freopen("in.txt" ,"r" , stdin) ;
    int n , m ;
    while(scanf("%d%d" , &n , &m) &&(n+m))
    {
        int op , x ,  y , c;
        build(1 , n , 1) ;
        while(m--)
        {
            scanf("%d%d%d%d" , &op , &x , &y , &c) ;
            if(op == 4)
            printf("%d\n" , (query(x, y , 1 , c)%mod)) ;
            else update(x , y , 1 , op , c) ;
        }
    }
    return  0 ;
}





0 0
原创粉丝点击