[CodeChef April Challenge 2014] FBCHEF

Description

给出一棵n个点的,以1为根的有根树,每个点有点权wi
q次操作,有两种操作:
1 A X:对于所有的点B,定义dis(A,B)为A到B路径上的边数,将B的权值减去 ⌊ X 2 d i s ( A , B ) ⌋ \lfloor {X\over {2^{dis(A,B)}}}\rfloor 2dis(A,B)X
2 A:问以A为根的子树内,有多少个点的点权<=0
n,q,X<=10^5

Solution

先考虑修改在询问前的做法
设F[x][k]表示以x为根的子树内,到x距离为k的点的修改值
那么一次修改我们会修改F[A][0…16],F[father[A]][0…15],…
然后我们询问考虑直接问A的每个祖先B的F[B][dis(A,B)]
注意到这里可能会算重,于是我们F数组记得实际上是修改值的差分值
注意到点权只会减少,于是我们可以考虑求出所有点第一次变成非正的时间
这个东西可以直接套整体二分
考虑一次修改复杂度为O(log^2 A),询问复杂度为O(log A),于是我们可以预先把操作加入,然后可持久化一下,这样整体二分的时候就不用重新加入修改
因为我们不能在可持久化的数组上二分,我们可以直接维护一个指针扫一扫
整体二分的时候时间的流动是有序的,指针扫动的总次数为O(n log^2 A)
那么总复杂度就是O(n log^2 A)

Code

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a) for(int i=lst[a];i;i=nxt[i])
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
using namespace std;

typedef long long ll;

int read() {
	char ch;
	for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
	int x=ch-'0';
	for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x;
}

void write(int x) {
	if (!x) {puts("0");return;}
	char ch[20];int tot=0;
	for(;x;x/=10) ch[++tot]=x%10+'0';
	fd(i,tot,1) putchar(ch[i]);
	puts("");
}

const int N=1e5+5,D=17;

int t[N<<1],nxt[N<<1],lst[N],l;
void add(int x,int y) {t[++l]=y;nxt[l]=lst[x];lst[x]=l;}

int n,q,w[N],dfn[N],tot,tm,qu,fir[N],sz[N],fa[N],dep[N];

struct Ask{int x,t;}ask[N];
struct Atk{int x,v;}atk[N];

int tr[N];
void I(int x) {for(;x<=n;x+=x&-x) tr[x]++;}
int Q(int x) {int ret=0;for(;x;x-=x&-x) ret+=tr[x];return ret;}

int ord[N];
bool cmp(int x,int y) {return fir[x]<fir[y];}

void dfs(int x,int y) {
	fa[x]=y;dfn[x]=++tot;sz[x]=1;dep[x]=dep[y]+1;
	rep(i,x) if (t[i]!=y) dfs(t[i],x),sz[x]+=sz[t[i]];
}

int id[N],pt[N][D],p1[N],p2[N],cnt;
vector<ll> f[N][D];
vector<int> tim[N][D];

void solve(int l,int r,int x,int y) {
	if (l==r) {fo(i,x,y) fir[id[i]]=l;return;}
	int mid=l+r>>1,t1=0,t2=0;
	fo(i,x,y) {
		ll c=0;
		for(int z=id[i],j=0;j<=16&&z;z=fa[z],j++) {
			if (tim[z][j].empty()) continue;
			int pos=pt[z][j];
			while (pos<tim[z][j].size()-1&&tim[z][j][pos+1]<=mid) pos++,cnt++;
			while (pos>=0&&tim[z][j][pos]>mid) pos--,cnt++;
			if (pos>=0) c+=f[z][j][pos];
			pt[z][j]=max(pos,0);
		}
		if (c>=w[id[i]]) p1[++t1]=id[i];
		else p2[++t2]=id[i];
	}
	fo(i,1,t1) id[x+i-1]=p1[i];
	fo(i,1,t2) id[x+t1+i-1]=p2[i];
	solve(l,mid,x,x+t1-1);solve(mid+1,r,x+t1,y);
}

int main() {
	freopen("pang.in","r",stdin);
	freopen("pang.out","w",stdout);
	n=read();
	fo(i,1,n) w[i]=read();
	fo(i,1,n-1) {
		int x=read(),y=read();
		add(x,y);add(y,x);
	}
	q=read();dfs(1,0);
	tm=qu=0;
	fo(i,1,q) {
		int opt=read(),x=read();
		if (opt==1) atk[++tm].x=x,atk[tm].v=read();
		if (opt==2) ask[++qu].x=x,ask[qu].t=tm;
	}
	fo(i,1,tm) {
		int x=atk[i].x,v=atk[i].v;
		for(int j=0;j<=16&&x;j++,x=fa[x]) {
			fo(k,0,16-j) {
				ll tmp=(v>>j+k);
				if (fa[x]) tmp-=v>>j+k+2;
				if (!f[x][k].empty()) tmp+=f[x][k][f[x][k].size()-1];
				f[x][k].pb(tmp);tim[x][k].pb(i);
			}
		}
	}
	fo(i,1,n) id[i]=i;solve(1,tm+1,1,n);
	fo(i,1,n) ord[i]=i;sort(ord+1,ord+n+1,cmp);
	int j=0;
	fo(i,1,qu) {
		while (j<n&&fir[ord[j+1]]<=ask[i].t) I(dfn[ord[++j]]);
		write(Q(dfn[ask[i].x]+sz[ask[i].x]-1)-Q(dfn[ask[i].x]-1));
	}
	return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值