题解:
KDtree查询矩阵,如果最后一次修改的时间全部一样,那么直接在子树里讨论两种情况,线段树合并支持查询。
否则暴力递归删除子树标记,容易知道复杂度为 O ( n n log n ) O(n \sqrt{n} \log n) O(nnlogn)。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(LL x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}
const int N=1e5+50, T=1e9;
int n,Q,fa[N];LL dep[N];
int L[N],R[N],ind;
int lc[N*60],rc[N*60],tot;
LL sv[N*60],ss[N*60];
vector <int> g[N];
struct P {
LL x,y;
int val,sum;
} a[N];
inline bool cmpx(const P &a,const P &b) {return a.x<b.x || (a.x==b.x && a.y<b.y);}
inline bool cmpy(const P &a,const P &b) {return a.y<b.y || (a.y==b.y && a.x<b.x);}
struct node {
int rt,tag,last;
LL val,sum,x,y,mnx,mny,mxx,mxy;
} p[N<<2];
inline void dfs(int x) {
L[x]=++ind;
for(auto v:g[x])
dep[v]+=dep[x], dfs(v);
R[x]=ind;
}
inline void upt(int x,int y) {
p[x].mnx=min(p[x].mnx,p[y].mnx);
p[x].mny=min(p[x].mny,p[y].mny);
p[x].mxx=max(p[x].mxx,p[y].mxx);
p[x].mxy=max(p[x].mxy,p[y].mxy);
}
inline void upt(int k) {
sv[k]=sv[lc[k]]+sv[rc[k]];
ss[k]=ss[lc[k]]+ss[rc[k]];
}
inline void inc(int &k,int l,int r,int p,P &t) {
if(!k) k=++tot;
if(l==r) {
sv[k]=t.val;
ss[k]=t.sum;
return;
} int mid=(l+r)>>1;
(p<=mid) ? inc(lc[k],l,mid,p,t) : inc(rc[k],mid+1,r,p,t);
upt(k);
}
inline int merge(int x,int y) {
if(!x) return y;
if(!y) return x;
int z=++tot;
lc[z]=merge(lc[x],lc[y]);
rc[z]=merge(rc[x],rc[y]);
ss[z]=ss[x]+ss[y];
sv[z]=sv[x]+sv[y];
return z;
}
inline void build(int k,int l,int r,int dim) {
int mid=(l+r)>>1;
nth_element(a+l,a+mid,a+r+1,dim?cmpy:cmpx);
inc(p[k].rt,1,T,ceil((double)a[mid].sum/a[mid].val),a[mid]);
p[k].val=a[mid].val; p[k].sum=a[mid].sum;
p[k].x=p[k].mxx=p[k].mnx=a[mid].x;
p[k].y=p[k].mxy=p[k].mny=a[mid].y;
if(l<mid) {
build(k<<1,l,mid-1,dim^1);
p[k].rt=merge(p[k].rt,p[k<<1].rt);
upt(k,k<<1);
}
if(r>mid) {
build(k<<1|1,mid+1,r,dim^1);
p[k].rt=merge(p[k].rt,p[k<<1|1].rt);
upt(k,k<<1|1);
}
}
LL lx,rx,ly,ry;
inline int calc_insert(int k) {
if(lx<=p[k].mnx && p[k].mxx<=rx && ly<=p[k].mny && p[k].mxy<=ry) return 1;
if(p[k].mxx<lx || rx<p[k].mnx || p[k].mxy<ly || ry<p[k].mny) return -1;
return 0;
}
inline bool in(int k) {return (lx<=p[k].x && p[k].x<=rx && ly<=p[k].y && p[k].y<=ry);}
inline void cov(int k,int t) {p[k].tag=p[k].last=t;}
inline void pushdown(int k) {
if(!~p[k].tag) return;
cov(k<<1,p[k].tag);
cov(k<<1|1,p[k].tag);
p[k].tag=-1;
}
inline LL ask(int k,int l,int r,int L,int R,int type) {
if(!k) return 0;
if(L<=l && r<=R) {return type ? ss[k] : sv[k];}
int mid=(l+r)>>1;
if(R<=mid) return ask(lc[k],l,mid,L,R,type);
else if(L>mid) return ask(rc[k],mid+1,r,L,R,type);
else return ask(lc[k],l,mid,L,R,type)+ask(rc[k],mid+1,r,L,R,type);
}
inline LL calc_single(int k,LL t) {
LL v=min((t-p[k].last)*p[k].val,p[k].sum);
p[k].last=t; return v;
}
inline LL calc_tot(int k,LL t) {
int lim=(t-p[k].last);
LL val1=ask(p[k].rt,1,T,1,lim,1);
LL val2=(lim<=T) ? ask(p[k].rt,1,T,lim+1,T,0)*lim : 0;
cov(k,t); return val1+val2;
}
inline LL ask(int k,int t) {
if(!p[k].rt) return 0;
int v=calc_insert(k);
if(!~v) return 0;
LL ans=0;
if(v==1) {
if(~p[k].tag) {
ans+=calc_tot(k,t);
} else {
ans+=ask(k<<1,t);
ans+=ask(k<<1|1,t);
ans+=calc_single(k,t);
cov(k,t);
}
} else {
pushdown(k);
ans+=ask(k<<1,t);
ans+=ask(k<<1|1,t);
if(in(k)) ans+=calc_single(k,t);
} return ans;
}
int main() {
n=rd();
for(int i=1;i<=n;i++) a[i].val=rd();
for(int i=1;i<=n;i++) a[i].sum=rd();
for(int i=2;i<=n;i++)
g[rd()].push_back(i), dep[i]=rd();
dfs(1);
for(int i=1;i<=n;i++) a[i].x=L[i], a[i].y=dep[i];
build(1,1,n,0);
Q=rd();
for(int i=1;i<=Q;i++) {
int t=rd(), x=rd(), k=rd();
lx=L[x], rx=R[x], ly=dep[x], ry=dep[x]+k;
W(ask(1,t)), putchar('\n');
}
}