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

来源:互联网 发布:js bind 用法 编辑:程序博客网 时间:2024/06/01 17:37

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 longconst int Maxn=40010;int read(){    int 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<<3)+(x<<1)+ch-'0';ch=getchar();}    return x*f;}multiset<int>S[Maxn<<1];int n,m,q,k,F[Maxn],P[Maxn];//F武力值 P居住地struct A{int Len,b[22];}a[Maxn<<1];struct Tree{int l,r,lc,rc;}tr[Maxn<<1];int top[Maxn],tot[Maxn],dep[Maxn],son[Maxn],ys[Maxn],z=0,fa[Maxn];struct Edge{int y,next;}e[Maxn<<1];int last[Maxn],len=0;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]+1;tot[x]=1;    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=0;void build(int l,int r){    int t=++trlen;    tr[t].l=l;tr[t].r=r;    if(l<r)    {        int mid=l+r>>1;        tr[t].lc=trlen+1;build(l,mid);        tr[t].rc=trlen+1;build(mid+1,r);    }}A merge(A x,A y)//归并 {    int l1=1,l2=1;A re;re.Len=0;    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==1)S[pos].insert(x);        else S[pos].erase(S[pos].find(x));        a[now].Len=0;        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>>1;    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>>1;    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+1,r));        return re;    }}void solve(int x,int y){    int tx=top[x],ty=top[y];A ans;ans.Len=0;    while(tx!=ty)    {        if(dep[tx]<dep[ty])swap(tx,ty),swap(x,y);        ans=merge(ans,query(1,ys[tx],ys[x]));        x=fa[tx];tx=top[x];    }    if(dep[x]>dep[y])swap(x,y);    ans=merge(ans,query(1,ys[x],ys[y]));    if(!ans.Len){puts("-1");return;}    for(int i=1;i<=ans.Len;i++)printf("%d ",ans.b[i]);puts("");}int main(){    n=read();    for(int i=1;i<n;i++){int x=read(),y=read();ins(x,y);ins(y,x);}    dep[0]=0;dfs1(1,0);dfs2(1,1);build(1,z);    m=read();    for(int i=1;i<=m;i++)F[i]=read(),P[i]=read();    q=read();k=read();    for(int i=1;i<=m;i++)pos=P[i],change(1,ys[P[i]],F[i],1);    while(q--)    {        int op=read(),x=read(),y=read();        if(op==1)solve(x,y);        else if(op==2)pos=P[x],change(1,ys[P[x]],F[x],-1),P[x]=y,pos=P[x],change(1,ys[P[x]],F[x],1);        else pos=P[x],change(1,ys[P[x]],F[x],-1),F[x]=y,pos=P[x],change(1,ys[P[x]],F[x],1);    }}
原创粉丝点击