• HDU4578 Transformation【线段树】


    <题目链接>

    <转载于 >>> >

    题目大意:

    有一个序列,有四种操作:

    1:区间[l,r]内的数全部加c。

    2:区间[l,r]内的数全部乘c。

    3:区间[l,r]内的数全部初始为c。

    4:询问区间[l,r]内所有数的P次方之和。

    解题分析:

    不可能全部查询的节点,最好的情况就是查询到一段[l,r],这段区间内所有的值都相等,那么返回(r-l+1)*val 的值即可。只要标记区间内的所有数是否相同,并记录下区间内所有数相同的区间的值即可。每次询问时查询到区间内所有值相同的区间即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 const int mod=10007;
     8 const int M =1e5+5;
     9 
    10 #define Lson rt<<1,l,mid
    11 #define Rson rt<<1|1,mid+1,r
    12 int n,m;
    13 bool cnt[M<<2];
    14 ll tr[M<<2];
    15 void Pushdown(int rt){
    16     if(cnt[rt]){
    17         cnt[rt<<1]=cnt[rt<<1|1]=true;  
    18         tr[rt<<1]=tr[rt<<1|1]=tr[rt];  
    19     }
    20 }
    21 void Pushup(int rt){
    22     if(!cnt[rt<<1]||!cnt[rt<<1|1])cnt[rt]=false; 
    23     else if(tr[rt<<1]!=tr[rt<<1|1])cnt[rt]=false;
    24     else cnt[rt]=true,tr[rt]=tr[rt<<1];
    25 }
    26 void update(int rt,int l,int r,int L,int R,int c,int type){
    27     if(cnt[rt]&&L<=l&&r<=R){   
    28         if(type==1)tr[rt]=(tr[rt]+c)%mod;     //分三种情况进行操作
    29         else if(type==2)tr[rt]=(tr[rt]*c)%mod;
    30         else tr[rt]=c;
    31         return;
    32     }
    33     Pushdown(rt);
    34     int mid=(l+r)>>1;
    35     if(L<=mid)update(Lson,L,R,c,type);
    36     if(R>mid)update(Rson,L,R,c,type);
    37     Pushup(rt);
    38 }
    39 int query(int rt,int l,int r,int L,int R,int c){
    40     if(cnt[rt]&&L<=l&&r<=R){
    41         ll res=1;for(int i=1;i<=c;i++)res*=tr[rt];  //得到tr[rt]的c次方(因为c<=3,所以可以不用快速幂)
    42         res=res*(r-l+1);   //乘上区间长度
    43         return res%mod;
    44     }
    45     Pushdown(rt);
    46     int mid=(l+r)>>1;
    47     ll ans=0;
    48     if(L<=mid)ans+=query(Lson,L,R,c);
    49     if(R>mid)ans+=query(Rson,L,R,c);
    50     return ans%mod;
    51 }
    52 int main(){
    53     while(scanf("%d%d",&n,&m)!=EOF,n||m){
    54         memset(tr,0,sizeof(tr));
    55         memset(cnt,true,sizeof(cnt));
    56         while(m--){
    57             int op,x,y,c;
    58             scanf("%d%d%d%d",&op,&x,&y,&c);
    59             if(op>=1&&op<=3)update(1,1,n,x,y,c,op);
    60             else printf("%d
    ",query(1,1,n,x,y,c));
    61         }
    62     }
    63     return 0;
    64 }

    2018-09-25

  • 相关阅读:
    三.装饰器函数
    二.函数进阶
    生成器
    一个列表实现__iter__和__next__方法的例子
    可迭代对象和迭代器
    asyncio模块实现线程的嵌套和穿插
    线程的阻塞
    利用collections下的counter实现对列表重复元素的查重
    queue的一些用法
    利用python deque的extend特性实现列表元素查重
  • 原文地址:https://www.cnblogs.com/00isok/p/9704280.html
Copyright © 2020-2023  润新知