2017集训队作业自选题#111: 资源采集(KD树)

题解:
KDtree查询矩阵,如果最后一次修改的时间全部一样,那么直接在子树里讨论两种情况,线段树合并支持查询。

否则暴力递归删除子树标记,容易知道复杂度为 O ( n n log ⁡ n ) O(n \sqrt{n} \log n) O(nn logn)

#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');
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值