Codeforces Round #381 (Div. 1) B Alyona and a tree 樹狀數組

B. Alyona and a tree

題意:給定一棵樹,樹上的邊有權值爲val[i],點有權值爲a[i],定義dist(a,b)爲a到b的路徑上的邊權的和

定義v控制u,當且僅當v是u的祖先且dist(u,v)<=a[u];


第一反應樹形dp嘛,可行,不過感覺略麻煩。。。而且二分的還要判斷一些奇怪的東西(好吧懶得打


因爲u是v的後代嘛。所以dist(u,v)=dist(1,u)-dist(1,v)

所以我們先處理出dist[i]=表示dist(1,i)


然後題目的要求可以轉化爲:v是u的祖先且dist(1,u)-dist(1,v)<=a[u]  ==》 dist(1,u)-a[u]<=dist(1,v)

這個東西貌似可以樹狀數組維護前綴和??

第一反應:按時間戳插入dist[i]-a[i],每次得到dist[i]作爲i的答案

然而。。。。1e9

gg

換一種思路


我們按照dist[i]-a[i]插入。對於詢問dist[i]

獲得此時  時間戳之間的所有已經被插入的點

完全可行

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define maxn 500001
#define inf 1e9
#define ll long long
#define For(i,j,k) for(ll i=j;i<=k;i++)
#define Dow(i,j,k) for(iny i=k;i>=j;i--)
using namespace std;
inline void read(ll &tx){   ll x=0,f=1;char ch=getchar();   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  tx=x*f; }
inline void write(ll x){    if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10);   putchar(x%10+'0');  }
inline void writeln(ll x){write(x);puts("");}
using namespace std;
struct point{ll num,ki,V;}	p[maxn];
bool vis[maxn];
ll f[maxn],poi[maxn],nxt[maxn],F[maxn],a[maxn],ans[maxn],n,tim,in[maxn],out[maxn],dist[maxn],v[maxn],cnt,x,y,tot;
inline bool cmp(point x,point y){return x.V!=y.V?x.V<y.V:x.ki<y.ki;}
inline void dfs(ll x,ll dis)
{
	dist[x]=dis;in[x]=++tim;
	vis[x]=1;
	for(ll i=f[x];i;i=nxt[i])
		if(!vis[poi[i]])	dfs(poi[i],dis+v[i]);
	out[x]=++tim;
}
inline ll lowbit(ll x){return x&-x;}
inline ll get(ll x){ll sum=0;for(ll i=x;i;i-=lowbit(i))	sum+=F[i];return sum;}
inline void add(ll x,ll v){for(ll i=x;i<=tim;i+=lowbit(i))	F[i]+=v;}
inline void add_edge(ll x,ll y,ll z){poi[++cnt]=y;nxt[cnt]=f[x];f[x]=cnt;v[cnt]=z;}
int main()
{
	read(n);
	For(i,1,n)	read(a[i]);
	For(i,1,n-1)	read(x),read(y),add_edge(x,i+1,y);
	dfs(1,0);
	For(i,1,n)	
	{
		point tmp;
		tmp.V=dist[i];tmp.ki=2;tmp.num=i;
		p[++tot]=tmp;
		tmp.V=dist[i]-a[i];tmp.ki=1;
		p[++tot]=tmp;
	}
	sort(p+1,p+tot+1,cmp);
	For(i,1,tot)
	{
		if(p[i].ki==2)	ans[p[i].num]=get(out[p[i].num])-get(in[p[i].num]-1);
			else 	add(in[p[i].num],1);
	}
	For(i,1,n)	write(ans[i]-1),putchar(' ');
}	


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章