BZOJ1798: [Ahoi2009]Seq 维护序列seq

Posted Troy Ricardo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1798: [Ahoi2009]Seq 维护序列seq相关的知识,希望对你有一定的参考价值。

题目链接:

  TP

題解:

  线段树玩法真心多233

  以前见过类似的题,但没写,今天做LCT发现一道双修改,尴尬的发现自己不太会2333,然后zyf就一脸嫌弃的告诉我先写这道线段树的版本emmmmmmm

  自己YY了好久,发现总会被时间顺序日到……看了题解(我是大蒟蒻……

  因为我一直都想把两种操作分离开,事实上没必要,因为发现对于已经加过的数值$plus$,假设我们没有将这个值传下去,那么下次修改时,若我们将其乘上一个数$mul$,事实上按照时间顺序,我们其实也要把该值乘上$mul$。所以我们可以直接将$plus$乘上$mul$,等到以后再传下去。这样我们就有效的干掉了时间顺序。

代码:

 1 #define Troy
 2 
 3 #include "bits/stdc++.h"
 4 
 5 using namespace std;
 6 
 7 const int N=1e5+5;
 8 
 9 inline int read(){
10     int s=0,k=1;char ch=getchar();
11     while(ch<0|ch>9)    ch==-?k=-1:0,ch=getchar();
12     while(ch>47&ch<=9)    s=s*10+(ch^48),ch=getchar();
13     return s*k;
14 }
15 
16 int n,p,m;
17 
18 struct Tree{
19     int sum,mul,plu;
20     Tree *lc,*rc;
21     Tree(){sum=plu=0,mul=1;lc=rc=NULL;}
22 }*root,tree[N<<2];int cnt;
23 
24 inline void build(Tree *&u,int l,int r){
25     u=tree+cnt,++cnt;
26     if(l==r){
27         u->sum=read();return;
28     }int mid=l+r>>1;
29     build(u->lc,l,mid);
30     build(u->rc,mid+1,r);
31     u->sum=(u->lc->sum+u->rc->sum)%p;
32 }
33 
34 inline void push(Tree *u,int leth,int mul,int plu){
35     u->sum=(u->sum*1ll*mul+plu*1ll*(leth))%p;
36     u->mul=u->mul*1ll*mul%p;
37     u->plu=(u->plu*1ll*mul+plu)%p;
38 }   
39 
40 inline void pushdown(Tree *u,int l,int r){
41     int mid=l+r>>1;
42     push(u->lc,mid-l+1,u->mul,u->plu);
43     push(u->rc,r-mid,u->mul,u->plu);
44     u->mul=1,u->plu=0;
45 }
46 
47 inline void update_1(Tree *u,int l,int r,int x,int y,int val){
48     if(x<=l&&r<=y){
49         u->mul=(u->mul*1ll*val)%p;
50         u->plu=(u->plu*1ll*val)%p;
51         u->sum=(u->sum*1ll*val)%p;
52         return ;
53     }
54     int mid=l+r>>1;
55     pushdown(u,l,r);
56     if(y>mid)   update_1(u->rc,mid+1,r,x,y,val);
57     if(x<=mid)    update_1(u->lc,l,mid,x,y,val);
58     u->sum=(u->lc->sum+u->rc->sum)%p;
59 }
60 
61 inline void update_2(Tree *u,int l,int r,int x,int y,int val){
62     if(x<=l&&r<=y){
63         u->plu=(u->plu*1ll+val)%p;
64         u->sum=(u->sum+1ll*val*(r-l+1))%p;
65         return ;
66     }
67     int mid=l+r>>1;
68     pushdown(u,l,r);
69     if(y>mid)   update_2(u->rc,mid+1,r,x,y,val);
70     if(x<=mid)    update_2(u->lc,l,mid,x,y,val);
71     u->sum=(u->lc->sum+u->rc->sum)%p;
72 }
73 
74 inline int query(Tree *u,int l,int r,int x,int y){
75     if(x<=l&&r<=y)  return u->sum;
76     pushdown(u,l,r);
77     int mid=l+r>>1,ret=0;
78     if(x<=mid)  ret=query(u->lc,l,mid,x,y);
79     if(y>mid)   ret=(ret+query(u->rc,mid+1,r,x,y))%p;
80     return ret;
81 }
82 
83 int main(){
84     n=read(),p=read();
85     build(root,1,n);
86     m=read()+1;
87     register int opt,x,y,val;
88     while(--m){
89         opt=read();
90         x=read(),y=read();
91         if(opt!=3)  val=read()%p;
92         switch(opt){
93             case 1:update_1(root,1,n,x,y,val);break;
94             case 2:update_2(root,1,n,x,y,val);break;
95             case 3:printf("%d\n",query(root,1,n,x,y));
96         }
97     }
98 }

 

以上是关于BZOJ1798: [Ahoi2009]Seq 维护序列seq的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树)

BZOJ1798 [Ahoi2009]Seq 维护序列seq

bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)

bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树多重标记下传)

BZOJ 1798 [Ahoi2009]Seq 维护序列seq

bzoj1798: [Ahoi2009]Seq 维护序列seq