daklqw 的 T3(点分树上数据结构优化DP)
程序员文章站
2022-07-03 17:58:11
设fxf_xfx为从第xxx个事件开始做最多的收益。那么这个dpdpdp是按照时间线从后往前的dpdpdp,求每个点的做起点的答案可以简单的在每个点初始放一个A=K=P=0A=K=P=0A=K=P=0的时间即可解决。对于两个事件之间的转移,我们只需要这两个事件在树上的距离s1s1s1,最小多走多少距离可以到达一个奖励边刷分并且走回这两个点的最短路径s2s2s2,(贪心来说,如果我们绕路,那么一定是在一个最近的奖励边上面刷分)最短路径上本来有多少奖励边ccc。那么如果这两个事件之间可以让我们移动...
设为从第个事件开始做最多的收益。
那么这个是按照时间线从后往前的,求每个点的做起点的答案可以简单的在每个点初始放一个的时间即可解决。
对于两个事件之间的转移,我们只需要这两个事件
在树上的距离,
最小多走多少距离可以到达一个奖励边刷分并且走回这两个点的最短路径,(贪心来说,如果我们绕路,那么一定是在一个最近的奖励边上面刷分)
最短路径上本来有多少奖励边。
那么如果这两个事件之间可以让我们移动的事件有,
分类讨论一下即可得到在完成这两个事件的同时我们最多能刷多少分。
预处理出每个点离最近的奖励边距离之后,
发现上面三个值都是只和这两个事件在树上的路径有关,可以在点分树上维护。
那么一条路径变成了。
要么中途完全不刷分,在上面插入时间点:事件的时间组合上,价值:。
直接在上面用数据结构查。
要么中刷分,要么中刷分。
刷分的话就是对于多余的秒可以换的分,对于时间点分别开两个数据结构维护一下即可。
如果直接上线段树空间是的,都过不去。
将所有可能的插入和询问点,离散化后写树状数组,一个询问只会贡献个点,所以空间复杂度是的。
#include<bits/stdc++.h>
#define maxn 100005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std;
char Start;
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
template<class T>void read(T &res){
char ch;
for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
LL C;
int n,Q,T;
int h[maxn],D[maxn],A[maxn],K[maxn],P[maxn],c[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cst[maxn<<1],cnt_e=1;
void Node(int u,int v,int c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=c; }
bool cmp(const int &u,const int &v){ return A[u] == A[v] ? K[u] > K[v] : A[u] > A[v]; }
#define lim 19
int dep[maxn],fa[lim][maxn],fadis[lim][maxn],faminh[lim][maxn],facst[lim][maxn],sz[maxn];
vector<int>sb[maxn];
void dfs0(int u,int ff,int tsz,int &mn,int &rt){
int mx = 0;sz[u] = 1;
for(int i=info[u],v;i;i=Prev[i]) if((v=to[i])^ff && dep[v] == -1){
dfs0(v,u,tsz,mn,rt);
sz[u] += sz[v];
mx = max(mx , sz[v]);
}
if((mx = max(mx , tsz - sz[u])) < mn)
mn = mx , rt = u;
}
int Gert(int u,int tsz){
int mn = 0x3f3f3f3f , rt = -1;
dfs0(u,0,tsz,mn,rt);
return rt;
}
void ser(int u,int ff,int pa,int D,int ndis,int nh,int ncst){
nh = min(nh , h[u]);sz[u] = 1;
fa[D][u] = pa , fadis[D][u] = ndis , faminh[D][u] = nh , facst[D][u] = ncst;
for(int i=info[u],v;i;i=Prev[i]) if(dep[v=to[i]] == -1 && v!= ff)
ser(v,u,pa,D,ndis+1,nh,ncst+cst[i]) ,sz[u] += sz[v];
}
void Solve(int u,int d){
dep[u] = d;
ser(u,0,u,d,0,h[u],0);
for(int i=info[u],v;i;i=Prev[i]) if(dep[v=to[i]] == -1)
Solve(Gert(v,sz[v]),d+1);
}
#define maxp maxn * 250
vector<LL>rt[maxn][5];
int fd(vector<int>&s,int tim){
return lower_bound(s.begin(),s.end(),tim)-s.begin()+1;
}
void ins(vector<LL>&u,int p,LL v){
for(;p;p-=p&-p) u[p] = max(u[p],v);
}
LL qry(vector<LL>&u,int p){
LL r=-inf;
for(;p<u.size();p+=p&-p)
r = max(r , u[p]);
return r;
}
void upd(int u,LL val,int tim,int dh){
if(tim < 0) return;
ins(rt[u][0],fd(sb[u],tim),val);
ins(rt[u][tim&1?4:3],fd(sb[u],tim),val+C*tim);
if(tim - dh >= 0)
ins(rt[u][tim-dh&1?2:1],fd(sb[u],tim-dh),val+C*(tim-dh));
}
LL qry2(int u,int tim,int dh){
if(tim > T) return -inf;
LL r = qry(rt[u][0],fd(sb[u],tim));
r = max(r , qry(rt[u][1],fd(sb[u],tim)) - C * tim - ((tim&1) != 0) * C);
r = max(r , qry(rt[u][2],fd(sb[u],tim)) - C * tim - ((tim&1) != 1) * C);
if(tim + dh <= T)
r = max(r ,
max(
qry(rt[u][3],fd(sb[u],tim+dh)) - (tim + dh) * C - ((tim&1) != 0) * C ,
qry(rt[u][4],fd(sb[u],tim+dh)) - (tim + dh) * C - ((tim&1) != 1) * C
));
return r;
}
LL qry(int u,int tim){
LL r = 0;
if(tim + h[u] / 2 <= T) r = (T - tim - h[u] / 2) * C;
per(i,dep[u],0)
r = max(r , qry2(fa[i][u],tim + fadis[i][u],faminh[i][u]) + facst[i][u] * C);
return r;
}
bool chk(int a){ return 0 <= a && a <= T; }
char End;
int main(){
freopen("daklqw.in","r",stdin);
freopen("daklqw.out","w",stdout);
cerr<< (&End - &Start) / 1024 / 1024 << endl;
read(n),read(Q),read(T),read(C);
memset(h,0x3f,sizeof h);
memset(dep,-1,sizeof dep);
rep(i,1,n-1){
int u,v,w;read(u),read(v),read(w);
Node(u,v,w),Node(v,u,w);
if(w) h[u] = h[v] = 0;
}
rep(i,1,Q)
read(D[i]),read(A[i]),read(K[i]),read(P[i]),c[i] = i;
sort(c+1,c+1+Q,cmp);
queue<int>q;
rep(i,1,n) if(!h[i]) q.push(i);
for(int u;!q.empty();){
u = q.front() , q.pop();
for(int i=info[u],v;i;i=Prev[i]) if(h[v=to[i]] > h[u] + 2)
h[v] = h[u] + 2 , q.push(v);
}
Solve(Gert(1,n),0);
rep(i,1,Q){
int u = D[i];
per(j,dep[u],0){
if(chk(A[i]-fadis[j][u]))
sb[fa[j][u]].push_back(A[i]-fadis[j][u]);
if(chk(A[i]-fadis[j][u]-faminh[j][u]))
sb[fa[j][u]].push_back(A[i]-fadis[j][u]-faminh[j][u]);
if(chk(A[i]+K[i]+fadis[j][u]))
sb[fa[j][u]].push_back(A[i]+K[i]+fadis[j][u]);
if(chk(A[i]+K[i]+fadis[j][u]+faminh[j][u]))
sb[fa[j][u]].push_back(A[i]+K[i]+fadis[j][u]+faminh[j][u]);
}
}
rep(i,1,n){
sb[i].push_back(0),
sort(sb[i].begin(),sb[i].end()),
sb[i].resize(unique(sb[i].begin(),sb[i].end())-sb[i].begin());
rep(j,0,4) rt[i][j] = vector<LL>(sb[i].size()+1 , -inf);
}
rep(i,1,Q){
int u = c[i];
LL f = qry(D[u],A[u]+K[u]) + P[u];
per(j,dep[D[u]],0) upd(fa[j][D[u]],f+facst[j][D[u]]*C,A[u]-fadis[j][D[u]],faminh[j][D[u]]);
}
rep(i,1,n) printf("%lld%c",qry(i,0)," \n"[i==n]);
}
本文地址:https://blog.csdn.net/qq_35950004/article/details/107302341
上一篇: 剑指offer JZ45 扑克牌顺子 Python 解
下一篇: 小小垃圾桶