[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); }}
阅读全文
1 0
- [BZOJ]4336: BJOI2015 骑士的旅行 树链剖分+STL(multiset)
- BZOJ 4336 BJOI2015 骑士的旅行
- 4336: BJOI2015 骑士的旅行
- [BZOJ4336][BJOI2015]骑士的旅行(树链剖分+线段树+multiset+归并)
- bzoj4336: BJOI2015 骑士的旅行
- 2017.10.6 BJOI2015 bzoj4336 骑士的旅行
- POJ2488 骑士的旅行
- 【Bzoj4336】骑士的旅行
- BZOJ 4337 BJOI2015 树的同构 Hash
- BZOJ 4337: BJOI2015 树的同构|Hash
- bzoj 4337: BJOI2015 树的同构 树哈希
- BZOJ 4337: BJOI2015 树的同构
- poj 2488 骑士的旅行
- 骑士旅行
- 骑士旅行
- 骑士旅行
- 骑士旅行
- BZOJ 4338 BJOI2015 糖果
- 《Data Mining》学习——K-邻近(KNN,K-NearestNeighbor)
- 虚电路网络与数据报网络
- 归并排序
- Spring5源码解析-Spring框架中的事件和监听器
- bind(),call(),apply()区别
- [BZOJ]4336: BJOI2015 骑士的旅行 树链剖分+STL(multiset)
- 函数十个问答
- 签名-代码混淆Progurard-反编译
- UGUI +ScrollRect下实现动态添加grid子物体
- MySQL学习笔记(一):修改MySQL中的提示符
- ubuntu 17.10 常用软件安装
- 利用时间序列预测用户系统是否过载
- hbase常用命令
- Android5.0 显示系统(二)————SurfaceComposerClient