【JZOJ6370】基礎 fake 練習題

description

裝飾者坐在樹蔭下聽着長者講述以前的故事:
大神 yk 非常喜歡樹,便欽點班裏的 n 個小蒟蒻站在一棵 n 個點以 1 爲根的樹上,並且每個點上恰好有 1 個小蒟蒻。
大神 yk 非常喜歡 fake,尤其是 fake 比他弱的人。根據可靠消息,大神 yk 擬定了m 個假人計劃,每個假人計劃形如 fake 樹上從點 u 到點 v 的簡單路徑上站的小蒟蒻。但大神 yk 不喜歡拐角,所以假人計劃選擇的簡單路徑的端點滿足 v 在 1 到 u 的簡單路徑上或者 u 在 1 到 v 的簡單路徑上。
每個小蒟蒻畢竟是人,忍耐是有限度的,站在 i 號點的小蒟蒻的忍耐值爲 ci。當這個小蒟蒻被 fake 的次數超過 ci 後,這個小蒟蒻會非常地憤怒。
大神 yk 可以從 m 個假人計劃中選出任意多個執行,但是大神 yk 不想讓任意一個小蒟蒻感到憤怒,因爲這樣會破壞友誼。
裝飾者聽到這裏,很好奇大神 yk 最多能實施多少假人計劃。但是這個問題太簡單了,裝飾者秒掉了它。於是它被當成模擬賽的簽到題扔你做。


analysis

  • 美國的那個華萊士比你們不知道高到哪裏去了我跟他談笑風生

  • 對於每個操作,放在dfsdfs序深度最深的節點開始放操作

  • 然後對於放完所有操作的點,詢問一下是否超過了當前點的限載

  • 如果超過,考慮貪心把深度最淺的操作一個個刪掉,相當於給祖先節點釋放壓力

  • 那麼就用線段樹合併,合併每一個兒子節點

  • 感覺線段樹合併很智障,要認真記一下套路


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define MAXN 300005
#define MAXM MAXN*2
#define MAX MAXN*20
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])

using namespace std;

ll last[MAXM],next[MAXM],tov[MAXM];
ll tr[MAX],lson[MAX],rson[MAX];
ll c[MAXN],root[MAXN],depth[MAXN];
vector<ll>v[MAXN];
ll n,m,tot;

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline void link(ll x,ll y){next[++tot]=last[x],last[x]=tot,tov[tot]=y;}
inline void dfs(ll x,ll y){rep(i,x)if (tov[i]!=y)depth[tov[i]]=depth[x]+1,dfs(tov[i],x);}
inline void insert(ll &t,ll l,ll r,ll x)
{
	if (!t)t=++tot;++tr[t];
	if (l==r)return;ll mid=(l+r)>>1;
	if (x<=mid)insert(lson[t],l,mid,x);
	else insert(rson[t],mid+1,r,x);
}
inline void merge(ll x,ll y)
{
	if (!x || !y)return;tr[x]+=tr[y];
	merge(lson[x],lson[y]),merge(rson[x],rson[y]);
	if (!lson[x])lson[x]=lson[y];
	if (!rson[x])rson[x]=rson[y];
}
inline ll query(ll t,ll l,ll r,ll x,ll y)
{
	if (!t)return 0;
	if (l==x && y==r)return tr[t];
	ll mid=(l+r)>>1;
	if (y<=mid)return query(lson[t],l,mid,x,y);
	else if (x>mid)return query(rson[t],mid+1,r,x,y);
	else return query(lson[t],l,mid,x,mid)+query(rson[t],mid+1,r,mid+1,y);
}
inline void delet(ll t,ll l,ll r)
{
	if (!t)return;--tr[t];
	if (l==r)return;ll mid=(l+r)>>1;
	if (tr[lson[t]]>0)delet(lson[t],l,mid);
	else delet(rson[t],mid+1,r);
}
inline void dfs1(ll x,ll y)
{
	if (v[x].size()>0)fo(i,0,v[x].size()-1)insert(root[x],1,n,v[x][i]);
	rep(i,x)if (tov[i]!=y)dfs1(tov[i],x),merge(root[x],root[tov[i]]);
	while (query(root[x],1,n,1,depth[x])>c[x])delet(root[x],1,n);
}
int main()
{
	freopen("fake.in","r",stdin);
	freopen("fake.out","w",stdout);
	n=read(),m=read();fo(i,1,n)c[root[i]=i]=read();
	fo(i,1,n-1){ll x=read(),y=read();link(x,y),link(y,x);}
	depth[1]=1,dfs(1,0),tot=n;
	fo(i,1,m)
	{
		ll x=read(),y=read();
		if (depth[x]<depth[y])swap(x,y);
		v[x].push_back(depth[y]);
	}
	dfs1(1,0),printf("%lld\n",tr[1]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章