天天看点

[BZOJ]4336: BJOI2015 骑士的旅行 树链剖分+STL(multiset)

Description

在一片古老的土地上,有一个繁荣的文明。

这片大地几乎被森林覆盖,有N座城坐落其中。巧合的是,这N座城由恰好N-1条双向道路连接起来,使得任意两座城都是连通的。也就是说,这些城形成了树的结构,任意两座城之间有且仅有一条简单路径。在这个文明中,骑士是尤其受到尊崇的职业。任何一名骑士,都是其家族乃至家乡的荣耀。Henry从小就渴望成为一名能守护家乡、驱逐敌人的骑士。勤奋训练许多年后,Henry终于满18岁了。他决定离开家乡,向那些成名已久的骑士们发起挑战!根据Henry的调查,大陆上一共有M名受封骑士,不妨编号为1到M。第i个骑士居住在城Pi,武力值为Fi。Henry计划进行若干次旅行,每次从某座城出发沿着唯一的简单路径前往另一座城,同时会挑战路线上武力值最高的K个骑士(Henry的体力有限,为了提高水平,当然要挑战最强的骑士)。如果路线上的骑士不足K人,Henry会挑战遇到的所有人。每次旅行前,可能会有某些骑士的武力值或定居地发生变化,Henry自然会打听消息,并对计划做出调整。

为了在每次旅行时做好充分准备,Henry希望你能帮忙在每次旅行前计算出这条路线上他将挑战哪些对手。

题解:

%%%zyf2000,因为k很小,所以可以每个叶子结点开一个multiset,存这个结点有哪些骑士,同时对线段树每个结点建一个结构体,存当前这一段有哪些骑士,然后儿子更新父亲的时候就用归并排序那样合并就行了,其它没什么要注意的了。代码也不难写。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=;
int read()
{
    int x=,f=;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<)+(x<<)+ch-'0';ch=getchar();}
    return x*f;
}
multiset<int>S[Maxn<<];
int n,m,q,k,F[Maxn],P[Maxn];//F武力值 P居住地
struct A{int Len,b[];}a[Maxn<<];
struct Tree{int l,r,lc,rc;}tr[Maxn<<];
int top[Maxn],tot[Maxn],dep[Maxn],son[Maxn],ys[Maxn],z=,fa[Maxn];
struct Edge{int y,next;}e[Maxn<<];
int last[Maxn],len=;
void ins(int x,int y){int t=++len;e[t].y=y;e[t].next=last[x];last[x]=t;}
void dfs1(int x,int f)
{
    fa[x]=f;dep[x]=dep[f]+;tot[x]=;
    for(int i=last[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(y!=f)
        {
            dfs1(y,x);
            if(tot[y]>tot[son[x]])son[x]=y;
            tot[x]+=tot[y];
        }
    }
}
void dfs2(int x,int Top)
{
    top[x]=Top;ys[x]=++z;
    if(son[x])dfs2(son[x],Top);
    for(int i=last[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(y!=fa[x]&&y!=son[x])dfs2(y,y);
    }
}
int trlen=;
void build(int l,int r)
{
    int t=++trlen;
    tr[t].l=l;tr[t].r=r;
    if(l<r)
    {
        int mid=l+r>>;
        tr[t].lc=trlen+;build(l,mid);
        tr[t].rc=trlen+;build(mid+,r);
    }
}
A merge(A x,A y)//归并 
{
    int l1=,l2=;A re;re.Len=;
    while(l1<=x.Len&&l2<=y.Len&&re.Len<k)
    {
        if(x.b[l1]>y.b[l2])re.b[++re.Len]=x.b[l1++];
        else re.b[++re.Len]=y.b[l2++];
    }
    while(l1<=x.Len&&re.Len<k)re.b[++re.Len]=x.b[l1++];
    while(l2<=y.Len&&re.Len<k)re.b[++re.Len]=y.b[l2++];
    return re;
}
int pos;
void change(int now,int p,int x,int o)
{
    if(tr[now].l==tr[now].r)
    {
        multiset<int>::iterator t;
        if(o==)S[pos].insert(x);
        else S[pos].erase(S[pos].find(x));
        a[now].Len=;
        if(!S[pos].empty())
        {
            t=S[pos].end();t--;
            while(a[now].Len<k)
            {
                a[now].b[++a[now].Len]=*t;
                if(t==S[pos].begin())break;
                t--;
            }
        }
        return;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=tr[now].l+tr[now].r>>;
    if(p<=mid)change(lc,p,x,o);else change(rc,p,x,o);
    a[now]=merge(a[lc],a[rc]);
}
A query(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)return a[now];
    int lc=tr[now].lc,rc=tr[now].rc,mid=tr[now].l+tr[now].r>>;
    if(r<=mid)return query(lc,l,r);
    else if(l>mid)return query(rc,l,r);
    else
    {
        A re=merge(query(lc,l,mid),query(rc,mid+,r));
        return re;
    }
}
void solve(int x,int y)
{
    int tx=top[x],ty=top[y];A ans;ans.Len=;
    while(tx!=ty)
    {
        if(dep[tx]<dep[ty])swap(tx,ty),swap(x,y);
        ans=merge(ans,query(,ys[tx],ys[x]));
        x=fa[tx];tx=top[x];
    }
    if(dep[x]>dep[y])swap(x,y);
    ans=merge(ans,query(,ys[x],ys[y]));
    if(!ans.Len){puts("-1");return;}
    for(int i=;i<=ans.Len;i++)printf("%d ",ans.b[i]);puts("");
}
int main()
{
    n=read();
    for(int i=;i<n;i++){int x=read(),y=read();ins(x,y);ins(y,x);}
    dep[]=;dfs1(,);dfs2(,);build(,z);
    m=read();
    for(int i=;i<=m;i++)F[i]=read(),P[i]=read();
    q=read();k=read();
    for(int i=;i<=m;i++)pos=P[i],change(,ys[P[i]],F[i],);
    while(q--)
    {
        int op=read(),x=read(),y=read();
        if(op==)solve(x,y);
        else if(op==)pos=P[x],change(,ys[P[x]],F[x],-),P[x]=y,pos=P[x],change(,ys[P[x]],F[x],);
        else pos=P[x],change(,ys[P[x]],F[x],-),F[x]=y,pos=P[x],change(,ys[P[x]],F[x],);
    }
}