Noip模拟81 2021.10.20
T1 语言
比较简单的题,然后就瞎写了,所以考场上就我一个写了线段树的,所以我的常数。。。。
所以就枚举动词的位置,找前面后面有没有出现$4$即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read(){ 4 int x=0,f=1;char ch=getchar(); 5 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 6 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 7 return x*f; 8 } 9 const int NN=100005; 10 int T,w[27],n,a[NN]; 11 char s[NN]; 12 struct SNOWtree{ 13 #define lid (id<<1) 14 #define rid (id<<1|1) 15 int ll[NN<<2],rr[NN<<2],sm[NN<<2][8]; 16 inline void pushup(int id){ 17 if(ll[id]==rr[id]) return; 18 for(int i=1;i<=7;++i) sm[id][i]=sm[lid][i]+sm[rid][i]; 19 } 20 inline void build(int id,int l,int r){ 21 ll[id]=l; rr[id]=r; 22 if(l==r){ 23 ++sm[id][a[l]];return; 24 }int mid=l+r>>1; 25 build(lid,l,mid); build(rid,mid+1,r); 26 pushup(id); 27 } 28 inline int query(int id,int l,int r,int opt){ 29 if(l<=ll[id]&&rr[id]<=r)return sm[id][opt]; 30 int mid=ll[id]+rr[id]>>1,ans=0; 31 if(l<=mid) ans+=query(lid,l,r,opt); 32 if(r>mid) ans+=query(rid,l,r,opt); 33 return ans; 34 } 35 }tr; 36 inline bool check(int i,int x){ 37 if(i-1==0||i==n) return 0; 38 if(x==1||x==2||x==3) return 0; 39 if(a[i-1]==1||a[i-1]==4||a[i-1]==5) return 0; 40 if(tr.query(1,1,i-2,4)!=0||tr.query(1,i+1,n-1,4)!=0) return 0; 41 return 1; 42 } 43 namespace WSN{ 44 inline short main(){ 45 // freopen("in.in","r",stdin); 46 freopen("language.in","r",stdin); 47 freopen("language.out","w",stdout); 48 T=read(); 49 while(T--){ 50 memset(a,0,sizeof(a)); 51 for(int i=1;i<=26;i++)w[i]=read(); 52 scanf("%s",s+1);n=strlen(s+1); 53 for(int i=1;i<=n;i++){ 54 int ch=s[i]-'a'+1; 55 a[i]=w[ch]; 56 } 57 if(a[n]!=2&&a[n]!=3&&a[n]!=6&&a[n]!=7){puts("No");continue;} 58 memset(tr.ll,0,sizeof(tr.ll)); 59 memset(tr.rr,0,sizeof(tr.rr)); 60 memset(tr.sm,0,sizeof(tr.sm)); 61 tr.build(1,1,n); bool flag=0; 62 for(int i=1;i<=n;i++) 63 if(check(i,a[i])){flag=1;break;} 64 puts(flag?"Yes":"No"); 65 } 66 return 0; 67 } 68 } 69 signed main(){return WSN::main();}
T2 色球
珂朵莉树写错一句话,就惨挂$30pts$,非常悲伤
于是先贴一个珂朵莉树的暴力
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read(){ 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x*f; 9 } 10 const int NN=200005; 11 int n,m,top[NN],tp; 12 char ch[5]; 13 namespace Chtholly{ 14 #define sit set<node>::iterator 15 struct node{ 16 int l,r; mutable int v; 17 node(int l,int r=0,int v=0):l(l),r(r),v(v){} 18 bool operator<(const node&a)const{return l<a.l;} 19 }; 20 set<node> s[NN]; 21 inline sit split(int i,int pos){ 22 sit it=s[i].lower_bound(pos); 23 if(it!=s[i].end()&&it->l==pos) return it; 24 --it; if(it->r<pos) return s[i].end(); 25 int L=it->l,R=it->r,V=it->v; 26 s[i].erase(it); 27 s[i].insert(node(L,pos-1,V)); 28 return s[i].insert(node(pos,R,V)).first; 29 } 30 inline void assign(int i,int l,int r,int v){ 31 sit itr=split(i,r+1),itl=split(i,l); 32 s[i].erase(itl,itr); 33 s[i].insert(node(l,r,v)); 34 } 35 }using namespace Chtholly; 36 namespace WSN{ 37 inline short main(){ 38 freopen("color.in","r",stdin); 39 freopen("color.out","w",stdout); 40 n=read(); m=read(); 41 for(int i=1;i<=n;i++) s[i].insert(node(0,1e18,0)); 42 while(m--){ 43 scanf("%s",ch); 44 if(ch[2]=='s'){ 45 int x=read(),y=read(),z=read(); 46 assign(z,top[z]+1,top[z]+x,y); 47 top[z]+=x; 48 } 49 if(ch[2]=='p'){ 50 int x=read(),z=read(),l=top[z]-x+1,r=top[z]; 51 sit itr=split(z,r+1),itl=split(z,l); 52 printf("%lld\n",itl->v); 53 assign(z,l,r,0); top[z]-=x; 54 } 55 if(ch[2]=='t'){ 56 int u=read(),v=read(); 57 sit it=s[u].end(); 58 if(it!=s[u].begin()) --it; 59 while(it!=s[u].begin()){ 60 if(it->v==0) {--it;continue;} 61 assign(v,top[v]+1,top[v]+it->r-it->l+1,it->v); 62 top[v]+=it->r-it->l+1; --it; 63 } 64 if(it->v!=0){ 65 assign(v,top[v]+1,top[v]+it->r-it->l+1,it->v); 66 top[v]+=it->r-it->l+1; 67 } 68 top[u]=0;s[u].clear();s[u].insert(node(0,1e18,0)); 69 } 70 } 71 return 0; 72 } 73 } 74 signed main(){return WSN::main();}
然后考虑双端队列的暴力,因为他可以优化成正解,
在直接双端队列的基础上使用启发式合并就行啦
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read(){ 5 int x=0;char ch=getchar(); 6 while(ch<'0'||ch>'9'){ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x; 9 } 10 const int NN=200005; 11 int n,m,top[NN]; 12 bool rev[NN]; 13 char ch[10]; 14 struct node{ 15 int num,col; 16 };deque<node> q[NN]; 17 namespace WSN{ 18 inline short main(){ 19 freopen("color.in","r",stdin); 20 freopen("color.out","w",stdout); 21 n=read(); m=read(); 22 for(int i=1;i<=n;i++)top[i]=i; 23 int u,v,x,y,z; 24 while(m--){ 25 cin>>ch; 26 if(ch[2]=='s'){ 27 x=read(),y=read(),z=read(); 28 if(!rev[z]) q[top[z]].push_back(node{x,y}); 29 else q[top[z]].push_front(node{x,y}); 30 } 31 if(ch[2]=='p'){ 32 x=read(),z=read(); node now; 33 if(!rev[z]){ 34 z=top[z]; 35 while(x&&!q[z].empty()){ 36 now=q[z].back(); q[z].pop_back(); 37 if(now.num>x){ 38 now.num-=x; q[z].push_back(node{now.num,now.col}); 39 printf("%lld\n",now.col); 40 break; 41 } 42 x-=now.num; if(!x) printf("%lld\n",now.col); 43 } 44 } 45 else{ 46 z=top[z]; 47 while(x&&!q[z].empty()){ 48 now=q[z].front(); q[z].pop_front(); 49 if(now.num>x){ 50 now.num-=x; q[z].push_front(node{now.num,now.col}); 51 printf("%lld\n",now.col); 52 break; 53 } 54 x-=now.num; if(!x) printf("%lld\n",now.col); 55 } 56 } 57 } 58 if(ch[2]=='t'){ 59 u=read(),v=read(); bool flag=false; 60 if(q[top[u]].size()>q[top[v]].size()) 61 swap(top[u],top[v]),swap(rev[u],rev[v]),flag=true; 62 if(!rev[u]&&!rev[v]) while(q[top[u]].size()) q[top[v]].push_back (q[top[u]].back()), q[top[u]].pop_back(); 63 else if(rev[u]&&!rev[v]) while(q[top[u]].size()) q[top[v]].push_back (q[top[u]].front()),q[top[u]].pop_front(); 64 else if(!rev[u]&&rev[v]) while(q[top[u]].size()) q[top[v]].push_front(q[top[u]].back()), q[top[u]].pop_back(); 65 else while(q[top[u]].size()) q[top[v]].push_front(q[top[u]].front()),q[top[u]].pop_front(); 66 if(flag) rev[v]^=1; 67 } 68 } 69 return 0; 70 } 71 } 72 signed main(){return WSN::main();}
T3 斐波
考场上推出来了个$f_i^2+f_{i+1}^2=f_{2i+1}$,但不知道怎么用,然后题解里的那个也没推出来,就死掉了
就咕咕咕
$UPD2021.10.26$这题卡常卡的我爽了,现在非常亢奋
按照题解说的维护矩阵$B_i=I+A^a_i$,那么答案就是$\sum\limits_{i=l}^{r}\sum\limits_{j=i}^{r}\prod\limits_{k=i}^{j}B_k \times \overrightarrow{g_0}$
其中$\overrightarrow{g_0}$初始化为$\begin{vmatrix}0&1&1\end{vmatrix}$
然后如果直接按照以上式子维护的话可获得$50pts$
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read(){ 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x*f; 9 } 10 const int NN=100005,mod=998244353; 11 int n,q,a[NN],fib[NN]; 12 namespace Matrix{ 13 struct Ma{ 14 int m[4][4]; 15 Ma(){memset(m,0,sizeof(m));} 16 inline void pre(){m[1][1]=m[2][2]=m[3][3]=1;} 17 inline void print(){ 18 for(int i=1;i<=3;i++){ 19 for(int j=1;j<=3;j++){ 20 cout<<m[i][j]<<" "; 21 }cout<<endl; 22 } 23 } 24 Ma operator*(const Ma&a)const{ Ma c; 25 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) 26 for(int k=1;k<=3;k++) c.m[i][j]=(c.m[i][j]+m[i][k]*a.m[k][j]%mod)%mod; 27 return c; 28 } 29 Ma operator+(const Ma&a)const{ Ma c; 30 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) 31 for(int k=1;k<=3;k++) c.m[i][j]=(m[i][j]+a.m[i][j])%mod; 32 return c; 33 } 34 }; 35 struct Li{ 36 int l[4]; 37 Li(){memset(l,0,sizeof(l));} 38 Li operator*(const Ma&a)const{ Li c; 39 for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) 40 c.l[i]=(c.l[i]+l[j]*a.m[i][j]%mod)%mod; 41 return c; 42 } 43 Li operator+(const Li&a)const{ Li c; 44 for(int i=1;i<=3;i++) c.l[i]=(l[i]+a.l[i])%mod; 45 return c; 46 } 47 }; 48 inline Ma ksm(Ma a,int b){ 49 Ma ans; ans.pre(); 50 for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a; 51 return ans; 52 } 53 }using namespace Matrix; 54 Ma A,I,B[NN]; 55 Li g; 56 inline void prework(){ 57 fib[1]=1;fib[2]=1; I.pre(); 58 for(int i=3;i<NN;i++)fib[i]=(fib[i-1]+fib[i-2])%mod; 59 A.m[1][1]=A.m[1][2]=2;A.m[2][1]=A.m[3][2]=1;A.m[1][3]=-1; 60 g.l[1]=0;g.l[2]=1;g.l[3]=1; 61 for(int i=1;i<=n;i++) B[i]=I+ksm(A,a[i]); 62 } 63 namespace WSN{ 64 inline short main(){ 65 // freopen("in.in","r",stdin); 66 freopen("fib.in","r",stdin);freopen("fib.out","w",stdout); 67 n=read();q=read();for(int i=1;i<=n;i++)a[i]=read(); 68 prework(); 69 while(q--){ 70 int opt=read(); 71 if(opt==1){ 72 int p=read(),v=read(); 73 B[p]=I+ksm(A,v); 74 } 75 if(opt==2){ 76 int l=read(),r=read(),an=0; 77 for(int i=l;i<=r;i++){ 78 for(int j=i;j<=r;j++){ 79 Ma ans;Li f;ans.pre(); 80 for(int k=i;k<=j;k++) ans=ans*B[k]; 81 f=g*ans; 82 an=(an+f.l[1]%mod)%mod; 83 } 84 } 85 printf("%lld\n",(an+mod)%mod); 86 } 87 } 88 return 0; 89 } 90 } 91 signed main(){return WSN::main();}
然后考虑用线段树维护答案,那么需要在线段树内维护四个矩阵,具体的$pushup$会比较妙
inline void pushup(int id){ if(ll[id]==rr[id])return; ms[id]=ms[lid]*ms[rid]; sum[id]=sum[lid]+sum[rid]+ls[rid]*rs[lid]; ls[id]=ls[lid]+ms[lid]*ls[rid]; rs[id]=rs[rid]+ms[rid]*rs[lid]; }
然后查询的时候使用那种带跨越区间合并的查询方式,就可以得到一段区间的答案,这样的复杂度是$O(3^3qlogn)$,预计得分$70pts$(???)
没错,就是只有$70$,常数大斩了!!!!
剩下的就只有卡常,$\huge{只有卡常!!}$
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read(){ 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x*f; 9 } 10 const int NN=100005,mod=998244353; 11 int n,q,a[NN]; 12 namespace Matrix{ 13 struct Ma{ 14 int m[3][3]; 15 Ma(){memset(m,0,sizeof(m));} 16 inline void pre(){m[0][0]=m[1][1]=m[2][2]=1;} 17 Ma operator*(const Ma&a)const{ Ma c; 18 for(int i=0;i<3;++i) for(int j=0;j<3;++j){ 19 for(int k=0;k<3;++k) c.m[i][j]+=m[i][k]*a.m[k][j]%mod; 20 c.m[i][j]%=mod; 21 } return c; 22 } 23 Ma operator+(const Ma&a)const{ Ma c; 24 for(int i=0;i<3;++i) for(int j=0;j<3;++j) 25 c.m[i][j]=(m[i][j]+a.m[i][j])%mod; 26 return c; 27 } 28 }; 29 struct Li{ 30 int l[3]; 31 Li(){memset(l,0,sizeof(l));} 32 Li operator*(const Ma&a)const{ Li c; 33 for(int i=0;i<3;++i){ 34 for(int j=0;j<3;++j) c.l[i]+=l[j]*a.m[i][j]%mod; 35 c.l[i]%=mod; 36 } return c; 37 } 38 Li operator+(const Li&a)const{ Li c; 39 for(int i=0;i<3;i++) c.l[i]=(l[i]+a.l[i])%mod; 40 return c; 41 } 42 }; 43 auto ksm=[](Ma a,int b){ 44 Ma ans; ans.pre(); 45 for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a; 46 return ans; 47 }; 48 }using namespace Matrix; 49 Ma A,I,B[NN]; 50 Li g; 51 auto prework=[](){ 52 I.pre(); g.l[0]=0;g.l[1]=1;g.l[2]=1; 53 A.m[0][0]=A.m[0][1]=2;A.m[1][0]=A.m[2][1]=1;A.m[0][2]=-1; 54 for(int i=1;i<=n;i++) B[i]=I+ksm(A,a[i]); 55 }; 56 struct SNOWtree{ 57 #define lid (id<<1) 58 #define rid (id<<1|1) 59 int ll[NN<<2],rr[NN<<2]; 60 Ma sum[NN<<2],ls[NN<<2],rs[NN<<2],ms[NN<<2]; 61 inline void pushup(int id){ 62 if(ll[id]==rr[id])return; 63 ms[id]=ms[lid]*ms[rid]; 64 sum[id]=sum[lid]+sum[rid]+ls[rid]*rs[lid]; 65 ls[id]=ls[lid]+ms[lid]*ls[rid]; 66 rs[id]=rs[rid]+ms[rid]*rs[lid]; 67 } 68 inline void build(int id,int l,int r){ 69 ll[id]=l;rr[id]=r;if(l==r) return ls[id]=rs[id]=ms[id]=sum[id]=B[l],void(); 70 int mid=l+r>>1; build(lid,l,mid); build(rid,mid+1,r); pushup(id); 71 } 72 inline void update(int id,int pos,int v){ 73 if(ll[id]==rr[id]) return sum[id]=ls[id]=rs[id]=ms[id]=I+ksm(A,v),void(); 74 int mid=ll[id]+rr[id]>>1;if(pos<=mid)update(lid,pos,v);else update(rid,pos,v); 75 pushup(id); 76 } 77 struct answer{Ma ms,sum,ls,rs;}; 78 inline answer query(int id,int l,int r){ 79 if(l<=ll[id]&&rr[id]<=r) return answer{ms[id],sum[id],ls[id],rs[id]}; 80 int mid=ll[id]+rr[id]>>1;answer ans; 81 if(r<=mid)return query(lid,l,r);if(l>mid)return query(rid,l,r); 82 answer t1=query(lid,l,mid),t2=query(rid,mid+1,r); 83 return answer{t1.ms*t2.ms,t1.sum+t2.sum+t1.rs*t2.ls,t1.ls+t1.ms*t2.ls,t2.rs+t2.ms*t1.rs}; 84 } 85 }tr; 86 Ma tmp;Li res; 87 int opt,l,r,p,v; 88 namespace WSN{ 89 inline short main(){ 90 // freopen("in.in","r",stdin); 91 freopen("fib.in","r",stdin);freopen("fib.out","w",stdout); 92 n=read();q=read();for(int i=1;i<=n;i++)a[i]=read(); 93 prework(); tr.build(1,1,n); 94 while(q--){ 95 opt=read(); 96 if(opt==1) p=read(),v=read(),tr.update(1,p,v); 97 if(opt==2){ 98 l=read(),r=read(); 99 tmp=tr.query(1,l,r).sum; res=g*tmp; 100 printf("%lld\n",(res.l[0]+mod)%mod); 101 } 102 } 103 return 0; 104 } 105 } 106 signed main(){return WSN::main();}
1 %:pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 #define int long long 4 const int NN=100001,mod=998244353; 5 namespace AE86{ 6 auto read=[](){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 10 return x*f; 11 }; 12 auto write=[](int x,char opt='\n'){ 13 char ch[20];short len=0;if(x<0)x=~x+1,putchar('-'); 14 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 15 for(short i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt); 16 }; 17 }using namespace AE86; 18 signed n,q,a[NN]; 19 namespace Matrix{ 20 struct Ma{ 21 int m[3][3]; 22 Ma(){memset(m,0,sizeof(m));} 23 inline void pre(){m[0][0]=m[1][1]=m[2][2]=1;} 24 inline Ma operator*(const Ma&a)const{ Ma c; 25 c.m[0][0]=c.m[0][0]+m[0][0]*a.m[0][0]%mod; 26 c.m[0][0]=c.m[0][0]+m[0][1]*a.m[1][0]%mod; 27 c.m[0][0]=c.m[0][0]+m[0][2]*a.m[2][0]%mod; c.m[0][0]%=mod; 28 c.m[0][1]=c.m[0][1]+m[0][0]*a.m[0][1]%mod; 29 c.m[0][1]=c.m[0][1]+m[0][1]*a.m[1][1]%mod; 30 c.m[0][1]=c.m[0][1]+m[0][2]*a.m[2][1]%mod; c.m[0][1]%=mod; 31 c.m[0][2]=c.m[0][2]+m[0][0]*a.m[0][2]%mod; 32 c.m[0][2]=c.m[0][2]+m[0][1]*a.m[1][2]%mod; 33 c.m[0][2]=c.m[0][2]+m[0][2]*a.m[2][2]%mod; c.m[0][2]%=mod; 34 c.m[1][0]=c.m[1][0]+m[1][0]*a.m[0][0]%mod; 35 c.m[1][0]=c.m[1][0]+m[1][1]*a.m[1][0]%mod; 36 c.m[1][0]=c.m[1][0]+m[1][2]*a.m[2][0]%mod; c.m[1][0]%=mod; 37 c.m[1][1]=c.m[1][1]+m[1][0]*a.m[0][1]%mod; 38 c.m[1][1]=c.m[1][1]+m[1][1]*a.m[1][1]%mod; 39 c.m[1][1]=c.m[1][1]+m[1][2]*a.m[2][1]%mod; c.m[1][1]%=mod; 40 c.m[1][2]=c.m[1][2]+m[1][0]*a.m[0][2]%mod; 41 c.m[1][2]=c.m[1][2]+m[1][1]*a.m[1][2]%mod; 42 c.m[1][2]=c.m[1][2]+m[1][2]*a.m[2][2]%mod; c.m[1][2]%=mod; 43 c.m[2][0]=c.m[2][0]+m[2][0]*a.m[0][0]%mod; 44 c.m[2][0]=c.m[2][0]+m[2][1]*a.m[1][0]%mod; 45 c.m[2][0]=c.m[2][0]+m[2][2]*a.m[2][0]%mod; c.m[2][0]%=mod; 46 c.m[2][1]=c.m[2][1]+m[2][0]*a.m[0][1]%mod; 47 c.m[2][1]=c.m[2][1]+m[2][1]*a.m[1][1]%mod; 48 c.m[2][1]=c.m[2][1]+m[2][2]*a.m[2][1]%mod; c.m[2][1]%=mod; 49 c.m[2][2]=c.m[2][2]+m[2][0]*a.m[0][2]%mod; 50 c.m[2][2]=c.m[2][2]+m[2][1]*a.m[1][2]%mod; 51 c.m[2][2]=c.m[2][2]+m[2][2]*a.m[2][2]%mod; c.m[2][2]%=mod; 52 return c; 53 } 54 inline Ma operator+(const Ma&a)const{ Ma c; 55 c.m[0][0]=m[0][0]+a.m[0][0];c.m[0][0]%=mod; 56 c.m[0][1]=m[0][1]+a.m[0][1];c.m[0][1]%=mod; 57 c.m[0][2]=m[0][2]+a.m[0][2];c.m[0][2]%=mod; 58 c.m[1][0]=m[1][0]+a.m[1][0];c.m[1][0]%=mod; 59 c.m[1][1]=m[1][1]+a.m[1][1];c.m[1][1]%=mod; 60 c.m[1][2]=m[1][2]+a.m[1][2];c.m[1][2]%=mod; 61 c.m[2][0]=m[2][0]+a.m[2][0];c.m[2][0]%=mod; 62 c.m[2][1]=m[2][1]+a.m[2][1];c.m[2][1]%=mod; 63 c.m[2][2]=m[2][2]+a.m[2][2];c.m[2][2]%=mod; 64 return c; 65 } 66 }; 67 struct Li{ 68 int l[3]; 69 Li(){memset(l,0,sizeof(l));} 70 inline Li operator*(const Ma&a)const{ Li c; 71 c.l[0]=c.l[0]+l[0]*a.m[0][0]%mod; 72 c.l[0]=c.l[0]+l[1]*a.m[0][1]%mod; 73 c.l[0]=c.l[0]+l[2]*a.m[0][2]%mod;c.l[0]%=mod; 74 c.l[1]=c.l[1]+l[0]*a.m[1][0]%mod; 75 c.l[1]=c.l[1]+l[1]*a.m[1][1]%mod; 76 c.l[1]=c.l[1]+l[2]*a.m[1][2]%mod;c.l[1]%=mod; 77 c.l[2]=c.l[2]+l[0]*a.m[2][0]%mod; 78 c.l[2]=c.l[2]+l[1]*a.m[2][1]%mod; 79 c.l[2]=c.l[2]+l[2]*a.m[2][2]%mod;c.l[2]%=mod; 80 return c; 81 } 82 }; 83 auto ksm=[](Ma a,signed b){ 84 Ma ans; ans.pre(); 85 for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a; 86 return ans; 87 }; 88 }using namespace Matrix; 89 Ma A,I,B[NN]; 90 Li g; 91 auto prework=[](){ 92 I.pre(); g.l[0]=0;g.l[1]=1;g.l[2]=1; 93 A.m[0][0]=A.m[0][1]=2;A.m[1][0]=A.m[2][1]=1;A.m[0][2]=-1; 94 for(signed i=1;i<=n;++i) B[i]=I+ksm(A,a[i]); 95 }; 96 struct SNOWtree{ 97 #define lid (id<<1) 98 #define rid (id<<1|1) 99 signed ll[NN<<2],rr[NN<<2]; 100 Ma sum[NN<<2],ls[NN<<2],rs[NN<<2],ms[NN<<2]; 101 inline void pushup(signed id){ 102 if(ll[id]==rr[id])return; 103 ms[id]=ms[lid]*ms[rid]; 104 sum[id]=sum[lid]+sum[rid]+ls[rid]*rs[lid]; 105 ls[id]=ls[lid]+ms[lid]*ls[rid]; 106 rs[id]=rs[rid]+ms[rid]*rs[lid]; 107 } 108 inline void build(signed id,signed l,signed r){ 109 ll[id]=l;rr[id]=r;if(l==r) return ls[id]=rs[id]=ms[id]=sum[id]=B[l],void(); 110 signed mid=l+r>>1; build(lid,l,mid); build(rid,mid+1,r); pushup(id); 111 } 112 inline void update(signed id,signed pos,signed v){ 113 if(ll[id]==rr[id]) return sum[id]=ls[id]=rs[id]=ms[id]=I+ksm(A,v),void(); 114 signed mid=ll[id]+rr[id]>>1;if(pos<=mid)update(lid,pos,v);else update(rid,pos,v); 115 pushup(id); 116 } 117 struct answer{Ma ms,sum,ls,rs;}; 118 inline answer query(signed id,signed l,signed r){ 119 if(l<=ll[id]&&rr[id]<=r) return answer{ms[id],sum[id],ls[id],rs[id]}; 120 signed mid=ll[id]+rr[id]>>1; answer ans; 121 if(r<=mid)return query(lid,l,r);if(l>mid)return query(rid,l,r); 122 answer t1=query(lid,l,mid),t2=query(rid,mid+1,r); 123 return answer{t1.ms*t2.ms,t1.sum+t2.sum+t1.rs*t2.ls,t1.ls+t1.ms*t2.ls,t2.rs+t2.ms*t1.rs}; 124 } 125 }tr; 126 Ma tmp;Li res; 127 signed opt,l,r,p,v; 128 namespace WSN{ 129 inline short main(){ 130 freopen("fib.in","r",stdin);freopen("fib.out","w",stdout); 131 n=read();q=read();for(signed i=1;i<=n;++i)a[i]=read(); 132 prework(); tr.build(1,1,n); 133 while(q--){ 134 opt=read(); 135 if(opt==1) p=read(),v=read(),tr.update(1,p,v); 136 else l=read(),r=read(),tmp=tr.query(1,l,r).sum,res=g*tmp,write((res.l[0]+mod)%mod); 137 } 138 return 0; 139 } 140 } 141 signed main(){return WSN::main();}
T4 偶数
咕咕咕