#线段树,矩阵乘法#LOJ 3264「ROIR 2020 Day 2」海报
分析
设\(dp[i][0/1/2/3]\)表示以\(i\)结尾1的长度为0/1/2/3的最大值,
那么
\[\begin{cases}dp[i][0]=\max\{dp[i-1][\dots]\}\\dp[i][x]=dp[i-1][x-1]+a[i],x>0\end{cases}
\]
发现这个环只要保证开头和结尾的\(0/1/2/3\)相同即可,单点修改直接在线段树上维护广义矩阵乘法
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll;
const lll inf=1e15;
const int N=40011;
int n,Q,a[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline lll max(lll a,lll b){return a>b?a:b;}
struct maix{
lll p[4][4];
inline void Clear(){
for (rr int i=0;i<4;++i)
for (rr int j=0;j<4;++j)
p[i][j]=-inf;
}
inline maix operator *(const maix &B)const{
rr maix C; C.Clear();
for (rr int i=0;i<4;++i)
for (rr int j=0;j<4;++j)
for (rr int k=0;k<4;++k)
C.p[i][j]=max(C.p[i][j],p[i][k]+B.p[k][j]);
return C;
}
}w[N<<2];
inline void build(int k,int l,int r){
if (l==r){
rr maix C; C.Clear();
C.p[0][0]=C.p[1][0]=C.p[2][0]=C.p[3][0]=0;
C.p[0][1]=C.p[1][2]=C.p[2][3]=a[l],w[k]=C;
return;
}
rr int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
w[k]=w[k<<1]*w[k<<1|1];
}
inline void update(int k,int l,int r,int x){
if (l==r){
w[k].p[0][1]=w[k].p[1][2]=w[k].p[2][3]=a[l];
return;
}
rr int mid=(l+r)>>1;
if (x<=mid) update(k<<1,l,mid,x);
else update(k<<1|1,mid+1,r,x);
w[k]=w[k<<1]*w[k<<1|1];
}
inline void query(maix A){
rr lll ans=0;
for (rr int i=0;i<4;++i)
ans=max(ans,A.p[i][i]);
print(ans),putchar(10);
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
build(1,1,n),query(w[1]);
for (rr int Q=iut();Q;--Q){
rr int x=iut(),y=iut(); a[x]=y;
update(1,1,n,x),query(w[1]);
}
return 0;
}