# bzoj4182 Shopping

trick：dfs序优化

f[x][*]<-f[fdfn[dfn[x]+1]][*]  ||   f[fdfn[dfn2[x]+1]][*]

（点分治换成dot可以牺牲一个log搞出以x为根dfs序，算出x为根的连通块答案）

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=0;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*10+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}

namespace Miracle{
const int N=505;
const int M=4004;
const int inf=0x3f3f3f3f;
int n,m;
int w[N],c[N],d[N];
int ans;
struct node{
int nxt,to;
}e[2*N];
int hd[N],cnt;
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int sz[N];
int nowsz,rt;
bool vis[N];
void fin(int x,int fa){
sz[x]=1;
int mxsz=0;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa||vis[y]) continue;
fin(y,x);
sz[x]+=sz[y];
mxsz=max(mxsz,sz[y]);
}
mxsz=max(mxsz,nowsz-sz[x]);
if(mxsz<=nowsz/2) rt=x;
}
int dfn[N],dfn2[N],df;
int fdfn[N];
int f[N][M];
int q[M],l,r;
void wrk(int x){
//    memset(f[x],0,sizeof f[x]);
//    cout<<" wrk x "<<x<<" c "<<c[x]<<" d "<<d[x]<<" w "<<w[x]<<" d[133] "<<d[133]<<endl;
for(reg i=0;i<=m;++i) f[x][i]=f[fdfn[dfn2[x]+1]][i];
int y=fdfn[dfn[x]+1];
///    cout<<"with "<<y<<endl;
int lp=0;
for(reg yu=0;yu<min(c[x],m+1);++yu){
l=1,r=0;
for(reg p=0;p*c[x]+yu<=m;++p){
++lp;
//    cout<<" infor "<<yu<<" "<<p<<" "<<l<<" "<<r<<endl;
while(l<=r&&p-q[l]>d[x]) ++l;
if(l<=r) f[x][p*c[x]+yu]=max(f[x][p*c[x]+yu],f[y][q[l]*c[x]+yu]+(p-q[l])*w[x]);
while(l<=r&&f[y][q[r]*c[x]+yu]-q[r]*w[x]<=f[y][p*c[x]+yu]-p*w[x]) --r;
q[++r]=p;
}
}
//    cout<<" bac x "<<x<<" lp "<<lp<<endl;
}
void dfs(int x,int fa){
dfn[x]=++df;fdfn[df]=x;
sz[x]=1;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa||vis[y]) continue;
dfs(y,x);
sz[x]+=sz[y];
}
dfn2[x]=df;
}
void divi(int x){
rt=0;
fin(x,0);
df=0;
dfs(rt,0);
fdfn[df+1]=0;
for(reg i=df;i>=1;--i) wrk(fdfn[i]);

for(reg j=0;j<=m;++j){
ans=max(ans,f[rt][j]);
}
int tmp=rt;
vis[tmp]=1;
for(reg i=hd[tmp];i;i=e[i].nxt){
int y=e[i].to;
if(vis[y]) continue;
nowsz=sz[y];
divi(y);
}
}
void clear(){
memset(hd,0,sizeof hd);
cnt=0;df=0;ans=0;
memset(vis,0,sizeof vis);
}
int main(){
int t;rd(t);
while(t--){
clear();
rd(n);rd(m);
for(reg i=1;i<=n;++i) rd(w[i]);
for(reg i=1;i<=n;++i) rd(c[i]);
for(reg i=1;i<=n;++i) rd(d[i]);
int x,y;
for(reg i=1;i<n;++i){
}
nowsz=n;
divi(1);
printf("%d\n",ans);
//        prt(vis,1,n);
//        if(t==1)return 0;
}
return 0;
}

}
signed main(){
freopen("data.in","r",stdin);
freopen("my.out","w",stdout);
Miracle::main();
return 0;
}

/*
Author: *Miracle*
Date: 2019/3/20 7:29:17
*/

posted @ 2019-03-20 10:21  *Miracle*  阅读(106)  评论(0编辑  收藏