Loading

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();}
View Code

 

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();}
View Code

然后考虑双端队列的暴力,因为他可以优化成正解,

在直接双端队列的基础上使用启发式合并就行啦

 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();}
View Code

 

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();}
View Code

然后考虑用线段树维护答案,那么需要在线段树内维护四个矩阵,具体的$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();}
TLE70(更可读)
  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();}
看了会死100

 

 

T4 偶数

咕咕咕

posted @ 2021-10-22 08:41  雪域亡魂  阅读(128)  评论(0编辑  收藏  举报