luoguP4751模板动态 DP(加强版)
Posted zyybot
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP4751模板动态 DP(加强版)相关的知识,希望对你有一定的参考价值。
本人不会LCT。。只会全局平衡树
本题如何卡常?
其实也不用很夸张,稍微卡一卡即可
考虑最耗时的部分是Modify
先把Modify打成非递归版自不必说---①
然后考虑到(不管有没有封装结构体)用数组下表访问节点的话太慢了,然后全部改成指针~---②
接着看到维护区间信息的时候做矩阵乘法都是用max
封装的话会慢一些,所以改成宏(#define)---③
然后就是全部变量都开int(想不出开longlong的理由是什么。。。。)---④
变量的话能全局尽量全局(要是看不顺眼也可以不必)
能重复用就重复用,不要多次定义(特别是for里的变量,i,j,k什么的可以一次定义多次使用)---⑤
以上就是我自己打的优化了,这样就可以卡过
但是还可以更快
首先,快读的getchar()挺慢的
所以。。。
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
数组访问很耗时,对于不可以改成指针的数组,我们可以这样搞:
//对于一个这样的数组:
int example[Span1][Span2]..[SpanN];
//以下是一个合法的随机访问方式,也是我们最常写的
example[a1][a2]..[an]
//可以改成:
example[(((a1-1)*SpanN+(a2-1))*Span(N-1)+(a3-1))*Span(N-2)....+an]
//然而这还不是最快的,它还可以变成:
*(example+(((a1-1)*SpanN+(a2-1))*Span(N-1)+(a3-1))*Span(N-2)....+an)
然后还有。。。超级毒瘤的,去掉大部分封装。
pushup 封装?删掉!矩阵乘法封装?删掉!
然后你就会得到一个飞快并且可读性为负的代码
嘛~其他的优化就超出我的能力范围了。想要更好的体验请参考wys的各种论文(其实我也不知道具体有什么QAQ
至于算法实现,这不是重点,本题解只讲解有关卡常的东西。。
#include<cstdio>
#define ls (k->son[0])
#define rs (k->son[1])
#define Matrix(a,b,c,d) ((Matrix){{a,b,c,d}})
int _ta,_tb;
#define max(a,b) ((_ta=a)>(_tb=b)?a:b)
const int MaxN=1000000,inf=0x3f3f3f3f;
inline void read(int &ans)
{
ans=0;
int sign=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-')
c=getchar();
if(c=='-')
sign=-1,c=getchar();
while(c>='0'&&c<='9')
ans=ans*10+c-48,c=getchar();
ans*=sign;
return;
}
struct Matrix
{
int s[2][2];
friend inline Matrix operator * (const Matrix &a,const Matrix &b)
{
int i,j,k;
Matrix c;
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
c.s[i][j]=-inf;
for(k=0;k<2;++k)
c.s[i][j]=max(c.s[i][j],a.s[i][k]+b.s[k][j]);
}
return c;
}
};
int n,m,val[MaxN+1];
int head[MaxN+1],to[MaxN*2],next[MaxN*2],tot=0;
inline void add(const int &x,const int &y)
{
to[++tot]=y,next[tot]=head[x],head[x]=tot;
return;
}
int dep[MaxN+1],size[MaxN+1],fth[MaxN+1],wson[MaxN+1],lsize[MaxN+1];
inline void dfs1(int x)
{
// printf("dfs1 %d
",x);
size[x]=1;
for(int i=head[x];i;i=next[i])
if(!size[to[i]])
{
dep[to[i]]=dep[x]+1,fth[to[i]]=x,dfs1(to[i]),size[x]+=size[to[i]];
if(size[to[i]]>size[wson[x]])
wson[x]=to[i];
}
lsize[x]=size[x]-size[wson[x]];
return;
}
int f[MaxN+1][2],g[MaxN+1][2],v[MaxN+1];
inline void dfs2(int x)
{
v[x]=1,f[x][0]=g[x][0]=0,f[x][1]=g[x][1]=val[x];
if(wson[x])
{
dfs2(wson[x]);
f[x][0]+=max(f[wson[x]][1],f[wson[x]][0]),f[x][1]+=f[wson[x]][0];
}
for(int i=head[x];i;i=next[i])
if(!v[to[i]])
{
dfs2(to[i]);
g[x][0]+=max(f[to[i]][1],f[to[i]][0]),g[x][1]+=f[to[i]][0];
f[x][0]+=max(f[to[i]][1],f[to[i]][0]),f[x][1]+=f[to[i]][0];
}
return;
}
struct Node
{
Node *son[2],*f;
inline void pushup()
{
mtr2=mtr1;
if(son[0])
mtr2=son[0]->mtr2*mtr2;
if(son[1])
mtr2=mtr2*son[1]->mtr2;
return;
}
inline int Max()
{
return max(mtr2.s[0][0],mtr2.s[1][0]);
}
Matrix mtr1,mtr2;
}node[MaxN+1];
Node *root;
inline void pushup(Node *k)
{
k->mtr2=k->mtr1;
if(ls)
k->mtr2=ls->mtr2*k->mtr2;
if(rs)
k->mtr2=k->mtr2*rs->mtr2;
return;
}
int stack[MaxN+1],top;
inline Node *Build2(int l,int r)
{
// printf("Build2 %d %d
",l,r);
if(l>r)
return 0;
int i,cur=0,tot=0;
for(i=l;i<=r;++i)
tot+=lsize[stack[i]];
for(i=l,cur=lsize[stack[i]];i<=r;cur+=lsize[stack[++i]])
if(cur*2>=tot)
{
node[stack[i]].son[0]=Build2(l,i-1);
if(node[stack[i]].son[0])
node[stack[i]].son[0]->f=node+stack[i];
node[stack[i]].son[1]=Build2(i+1,r);
if(node[stack[i]].son[1])
node[stack[i]].son[1]->f=node+stack[i];
(node+stack[i])->pushup();
// printf("Matrix: %d %d %d %d
");
return node+stack[i];
}
return 0;
}
inline void Modify(int x,int val)
{
node[x].mtr1.s[1][0]+=val-::val[x];
::val[x]=val;
for(Node *k=node+x;k;k=k->f)
if(k->f&&k->f->son[0]!=k&&k->f->son[1]!=k)
{
// printf("1 %d
",x);
k->f->mtr1.s[0][0]-=k->Max();
k->f->mtr1.s[1][0]-=k->mtr2.s[0][0];
// node[node[x].f].mtr1.s[0][1]=node[node[x].f].mtr1.s[0][0];
k->pushup();
k->f->mtr1.s[0][0]+=k->Max();
k->f->mtr1.s[0][1]=k->f->mtr1.s[0][0];
k->f->mtr1.s[1][0]+=k->mtr2.s[0][0];
}
else
k->pushup();
return;
}
inline Node *Build1(int top)
{
// printf("build1 %d
",top);
int i,x;
for(x=top;x;x=wson[x])
v[x]=1;
// puts("1");
for(x=top;x;x=wson[x])
for(i=head[x];i;i=next[i])
if(!v[to[i]])
Build1(to[i])->f=node+x;
// puts("2");
::top=0;
for(x=top;x;x=wson[x])
stack[++::top]=x;
return Build2(1,::top);
}
#include<cstring>
int main()
{
int i,a,b,lastans=0;
read(n),read(m);
// printf("%d %d
",n,m);
for(i=1;i<=n;++i)
read(val[i]);
for(i=1;i<n;++i)
read(a),read(b),add(a,b),add(b,a);
dfs1(1),dfs2(1);
memset(v,0,sizeof(v));
for(i=1;i<=n;++i)
node[i].mtr1=Matrix(g[i][0],g[i][0],g[i][1],-inf);
root=Build1(1);
// printf("%d
",Max(root));
for(i=1;i<=m;++i)
{
read(a),read(b),a^=lastans;
// printf("%d
",ans);
Modify(a,b);
printf("%d
",lastans=root->Max());
}
return 0;
}
以上是关于luoguP4751模板动态 DP(加强版)的主要内容,如果未能解决你的问题,请参考以下文章