<题目链接>
<转载于 >>> >
题目大意:
有一个序列,有四种操作:
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