ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【JZOJ6370】基础 fake 练习题

2019-10-04 20:53:07  阅读:248  来源: 互联网

标签:练习题 yk read ll mid JZOJ6370 fake root


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

  • 美国的那个华莱士比你们不知道高到哪里去了我跟他谈笑风生

  • 对于每个操作,放在\(dfs\)序深度最深的节点开始放操作

  • 然后对于放完所有操作的点,询问一下是否超过了当前点的限载

  • 如果超过,考虑贪心把深度最浅的操作一个个删掉,相当于给祖先节点释放压力

  • 那么就用线段树合并,合并每一个儿子节点

  • 感觉线段树合并很智障,要认真记一下套路


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;
}

标签:练习题,yk,read,ll,mid,JZOJ6370,fake,root
来源: https://www.cnblogs.com/horizonwd/p/11623245.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有