CF739C Alyona and towers题解
题意
给出一个长度为
广义矩乘
没学过矩乘请前往矩乘模板或看其它题解的思路。
我们先回顾常用的矩乘,假设
那么对于
广义矩乘就是把求和和乘法换成别的运算。
在广义矩阵乘法中,对于
这里要求两种算法有分配律,即对于任意
例如,在常用的矩乘中,有
本题做法
本题中,我们使用的广义矩阵乘法为
考虑直接 dp 怎么做。
设
设
设
将
于是,我们可以得出状态矩阵:
以及三个转移矩阵。
当
当
当
注意本题中的区间加减并不用真的去区间加减,只需要在差分数组上修改两个位置就好了,
复杂度
代码
这个做法虽然在码长和效率上不占优势,但是它好写啊,线段树是标准线段树,以及矩阵都只需要复制下来改一改就可以了。
#include<bits/stdc++.h>
#define cint const int
#define iint inline int
#define uint unsigned int
#define iuint inline unsigned int
#define cuint const unsigned int
#define ll long long
#define cll const long long
#define ill inline long long
#define ull unsigned long long
#define iull inline unsigned long long
#define cull const unsigned long long
#define sh short
#define csh const short
#define ish inline short
#define ush unsigned short
#define iush inline unsigned short
#define cush const unsigned short
using namespace std;
iint read()
{
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch-'0');
ch=getchar();
}
return x;
}
cint inf=1e9;
struct matrix{
short n,m;
int a[4][4];
}f,emp,A,B,C;
matrix operator*(const matrix x,const matrix y)
{
matrix z;
z.n=x.n;
z.m=y.m;
for(short i=0;i<x.n;++i)
{
for(short j=0;j<y.m;++j)
{
z.a[i][j]=-inf;
for(short k=0;k<x.m;++k)
{
z.a[i][j]=max(z.a[i][j],x.a[i][k]+y.a[k][j]);
}
}
}
return z;
}
inline void init()
{
emp.n=emp.m=4;
for(short i=0;i<4;++i)
{
for(short j=0;j<4;++j)
{
emp.a[i][j]=(i==j?0:-inf);
}
}
f.n=1;
f.m=4;
f.a[0][0]=f.a[0][1]=f.a[0][2]=f.a[0][3]=0;
B.n=B.m=4;
for(short i=0;i<4;++i)
{
for(short j=0;j<4;++j)
{
B.a[i][j]=(i==2?(j==2?0:1):-inf);
}
}
B.a[3][3]=0;
A=C=B;
A.a[0][0]=A.a[0][3]=1;
C.a[0][1]=C.a[1][1]=C.a[0][3]=C.a[1][3]=1;
}
int n,q;
ll a[300001];
namespace T{
struct node{
int l,r;
matrix prod;
}t[1200001];
void Build(cint p,cint l,cint r)
{
t[p].l=l;
t[p].r=r;
if(l==r)
{
if(a[l]>0)t[p].prod=A;
else if(a[l]==0)t[p].prod=B;
else t[p].prod=C;
return;
}
cint mid=l+r>>1;
Build(p<<1,l,mid);
Build(p<<1|1,mid+1,r);
t[p].prod=t[p<<1].prod*t[p<<1|1].prod;
}
void build()
{
Build(1,1,n);
}
void Update(cint p,cint x)
{
if(t[p].l>x||t[p].r<x)return;
if(t[p].l==x&&t[p].r==x)
{
if(a[x]>0)t[p].prod=A;
else if(a[x]==0)t[p].prod=B;
else t[p].prod=C;
return;
}
Update(p<<1,x);
Update(p<<1|1,x);
t[p].prod=t[p<<1].prod*t[p<<1|1].prod;
}
void update(cint x)
{
Update(1,x);
}
iint ask()
{
return (f*t[1].prod).a[0][3];
}
}
void solve()
{
cint l=read();
cint r=read();
cint d=read();
a[l]+=d;
T::update(l);
if(r!=n)
{
a[r+1]-=d;
T::update(r+1);
}
printf("%d\n",T::ask());
}
int main()
{
init();
n=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
}
for(int i=n;i>=1;--i)
{
a[i]-=a[i-1];
}
T::build();
q=read();
while(q--)solve();
return 0;
}