题解:JudgeOnline/upload/201604/Solution-4458.rar By jinlifu1999
超级钢琴...都已经成经典了
本来想打树链剖分和ST表的,后来看题解发现倍增更好打,膜打树链的Evan
题目后跟个题解链接是SMG
#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; typedef pair<ll,int> abcd; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void read(ll &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } int n,m,L,R,M; ll ans; int depth[500005]; ll s[500005]; int fat[500005][25]; abcd st[500005][25]; inline void build_fat(){ for (int k=1;k<=20;k++) for (int i=1;i<=n;i++) fat[i][k]=fat[fat[i][k-1]][k-1]; } inline int Fat(int u,int d){ for (int k=20;k>=0;k--) if ((d>>k)&1) u=fat[u][k]; return u; } inline void build_st(){ for (int i=0;i<=n;i++) st[i][0]=abcd(s[i],i); for (int k=1;k<=20;k++) for (int i=0;i<=n;i++) st[i][k]=min(st[i][k-1],st[fat[i][k-1]][k-1]); } inline abcd Query(int u,int d){ abcd ret(1LL<<60,0); for (int k=20;k>=0;k--) if ((d>>k)&1) ret=min(ret,st[u][k]),u=fat[u][k]; return ret; } struct node{ int u,l,r,m; ll val; node () { } node (int u,int l,int r):u(u),l(l),r(r) { } void calc(){ int f=Fat(u,l+1); abcd ret=Query(f,r-l); val=s[u]-ret.first; m=depth[u]-depth[ret.second]; } bool operator < (const node &B) const{ return val<B.val; } }; priority_queue<node> Q; int main() { int l,r; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); for (int i=1;i<=n;i++) read(fat[i][0]); for (int i=1;i<=n;i++) read(s[i]); read(M); read(L); read(R); for (int i=1;i<=n;i++) s[i]+=s[fat[i][0]],depth[i]=depth[fat[i][0]]+1; build_fat(); build_st(); node tmp; for (int i=1;i<=n;i++) { if (L>depth[i]) continue; l=L-1; r=min(R,depth[i]); if (l<r) { tmp=node(i,l,r); tmp.calc(); Q.push(tmp); } } for (int i=1;i<=M;i++) { if (Q.empty()) return printf("-01\n"),0; tmp=Q.top(); Q.pop(); ans+=tmp.val; int m=tmp.m,l=tmp.l,r=tmp.r,u=tmp.u; if (l<m-1) { tmp=node(u,l,m-1); tmp.calc(); Q.push(tmp); } if (m<r) { tmp=node(u,m,r); tmp.calc(); Q.push(tmp); } } printf("%lld\n",ans); return 0; }