BZOJ4336: BJOI2015 骑士的旅行

Description

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

Input

第一行,一个整数N,表示有N座城,编号为1~N。
接下来N-1行,每行两个整数Ui和Vi,表示城Ui和城Vi之间有一条道路相连。
第N+1行,一个整数M,表示有M个骑士。
接下来M行,每行两个整数Fi和Pi。
按顺序依次表示编号为1~M的每名骑士的武力值和居住地。
第N+M+2行,两个整数Q,K,分别表示操作次数和每次旅行挑战的骑士数目上限。
接下来Q行,每行三个整数Ti,Xi,Yi。Ti取值范围为{1,2,3},表示操作类型。
一共有以下三种类型的操作:
Ti=1时表示一次旅行,Henry将从城Xi出发前往城市Yi;
Ti=2时表示编号为Xi的骑士的居住地搬到城Yi;
Ti=3时表示编号为Xi的骑士的武力值修正为Yi。

Output

输出若干行,依次为每个旅行的答案。
对每个Ti=1的询问,输出一行,按从大到小的顺序输出Henry在这次旅行中挑战的所有骑士的武力值。
如果路线上没有骑士,输出一行,为一个整数-1。

Sample Input

5
1 2
1 3
2 4
2 5
4
10 1
6 1
14 5
7 3
5 3
1 2 3
1 5 3
1 4 4
2 1 4
1 2 3

Sample Output

10 7 6
14 10 7
-1
7 6

HINT

100%的数据中,1 ≤ N, M ≤ 40,000,1 ≤ Ui, Vi, Pi ≤ N,1 ≤ Q ≤ 80,000, 1 ≤ K ≤ 20,旅行次数不超过 40,000 次,武力值为不超过1,000的正整数。 
题解Here!
看了许多巨佬的博客,不是线段树+multiset,就是LCT+配对堆,弄得我好尴尬。。。
然后就自己YY了一个树链剖分+树状数组套主席树。。。
树上问题,直接一发树链剖分转换成序列上的问题。
将每一个骑士所在结点编号插入到对应的链剖过后的新编号的树状数组上。
每一次询问,提取出对应的区间所在的(log2n)个结点,然后进行k次二分,找到相应的k大值。
修改就暴力在树状数组上修改logn次即可。
所以预处理O(mlog2n),单次修改O(log2n),单次查询O(logn*logk*logx),x为骑士的武力值,上限1,000。
还是蛮稳的。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 50010
#define MAXM 1000
using namespace std;
int n,m,q,k,c=1,d=1;
int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
int root[MAXN];
struct Graph{int next,to;
}a[MAXN<<1];
struct Knight{int f,p;
}knight[MAXN];
inline int read(){int date=0,w=1;char c=0,last=0;while(c<'0'||c>'9'){last=c;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}if(last=='-')w=-1;return date*w;
}
namespace CT{int size=1;int s1,s2,lrt[MAXN],rrt[MAXN],left[MAXN],right[MAXN];struct Charman_Tree{int l,r,sum;}a[MAXN*300];void insert(int k,int v,int l,int r,int &rt){a[size]=a[rt];rt=size++;a[rt].sum+=v;if(l==r)return;int mid=l+r>>1;if(k<=mid)insert(k,v,l,mid,a[rt].l);else insert(k,v,mid+1,r,a[rt].r);}int query(int l,int r,int k){if(l==r)return l;int mid=l+r>>1,t=0;for(int i=1;i<=s1;i++)t-=a[a[lrt[i]].l].sum;for(int i=1;i<=s2;i++)t+=a[a[rrt[i]].l].sum;if(k<=t){for(int i=1;i<=s1;i++)lrt[i]=a[lrt[i]].l;for(int i=1;i<=s2;i++)rrt[i]=a[rrt[i]].l;return query(l,mid,k);}else{for(int i=1;i<=s1;i++)lrt[i]=a[lrt[i]].r;for(int i=1;i<=s2;i++)rrt[i]=a[rrt[i]].r;return query(mid+1,r,k-t);}}inline void init(){s1=s2=0;}inline int lowbit(int x){return x&(-x);}inline void update(int x,int k,int v){for(;x<=n;x+=lowbit(x))insert(k,v,1,MAXM,root[x]);}inline void add(int l,int r){for(int i=l-1;i;i-=lowbit(i))lrt[++s1]=root[i];for(int i=r;i;i-=lowbit(i))rrt[++s2]=root[i];}void Answer(){int sum=0,width;for(int i=1;i<=s1;i++){sum-=a[lrt[i]].sum;left[i]=lrt[i];}for(int i=1;i<=s2;i++){sum+=a[rrt[i]].sum;right[i]=rrt[i];}width=min(sum,k);if(width==0){printf("-1\n");return;}for(int i=1;i<=width;i++){for(int j=1;j<=s1;j++)lrt[j]=left[j];for(int j=1;j<=s2;j++)rrt[j]=right[j];printf("%d ",query(1,MAXM,sum-i+1));}printf("\n");}
}
inline void add(int x,int y){a[c].to=y;a[c].next=head[x];head[x]=c++;a[c].to=x;a[c].next=head[y];head[y]=c++;
}
void dfs1(int rt){son[rt]=0;size[rt]=1;for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(!deep[will]){deep[will]=deep[rt]+1;fa[will]=rt;dfs1(will);size[rt]+=size[will];if(size[son[rt]]<size[will])son[rt]=will;}}
}
void dfs2(int rt,int f){id[rt]=d++;top[rt]=f;if(son[rt])dfs2(son[rt],f);for(int i=head[rt];i;i=a[i].next){int will=a[i].to;if(will!=fa[rt]&&will!=son[rt])dfs2(will,will);}
}
void solve(int x,int y){CT::init();while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);CT::add(id[top[x]],id[x]);x=fa[top[x]];}if(deep[x]>deep[y])swap(x,y);CT::add(id[x],id[y]);CT::Answer();return;
}
void work(){int f,x,y;while(q--){f=read();x=read();y=read();if(f==1){solve(x,y);}else if(f==2){CT::update(id[knight[x].p],knight[x].f,-1);knight[x].p=y;CT::update(id[knight[x].p],knight[x].f,1);}else{CT::update(id[knight[x].p],knight[x].f,-1);knight[x].f=y;CT::update(id[knight[x].p],knight[x].f,1);}}
}
void init(){int x,y;n=read();for(int i=1;i<n;i++){x=read();y=read();add(x,y);}deep[1]=1;dfs1(1);dfs2(1,1);m=read();for(int i=1;i<=m;i++){knight[i].f=read();knight[i].p=read();CT::update(id[knight[i].p],knight[i].f,1);}q=read();k=read();
}
int main(){init();work();return 0;
}

  

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9376354.html

BZOJ4336: BJOI2015 骑士的旅行相关推荐

  1. 4336: BJOI2015 骑士的旅行

    4336: BJOI2015 骑士的旅行 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 282   Solved: 123 [ Submit][ ...

  2. BZOJ 4336 BJOI2015 骑士的旅行

    此题博主使用树状数组套树链剖分的做法 , 严格来说空间是不够用的 , 但是由于此题存在一个骑士的力量值的分部问题 , 如果边修改边开内存是完全没问题的. 骑士力量当作权值放在最外层用树状数组处理 , ...

  3. poj—2488骑士的旅程(深搜)

    题目: 骑士厌倦了一次又一次地看到相同的黑白方块,并决定 环游世界.每当骑士移动时,它都是一个方向上的两个正方形和一个垂直于此方向的正方形.骑士的世界就是他所生活的棋盘.我们的骑士住在一个棋盘上,这个 ...

  4. Knight Moves(骑士移动) (bfs经典模板题) POJ-2243

    题目:Knight Moves (骑士移动) 中文大意 A friend of you is doing research on the Traveling Knight Problem (TKP) ...

  5. 回溯算法和贪心算法_回溯算法介绍

    回溯算法和贪心算法 回溯算法 (Backtracking Algorithms) Backtracking is a general algorithm for finding all (or som ...

  6. 回溯算法和递归算法_回溯算法:递归和搜索示例说明

    回溯算法和递归算法 Examples where backtracking can be used to solve puzzles or problems include: 回溯可用于解决难题或问题 ...

  7. heheda练数据结构

    联赛结束,自己的码力已经下降了不知多少个档次,再加上最近空闲时间比较多,我就开启了这个可以说最费时间的专题. //话说我未完成的数论专题还会继续的. 最近看了以下知识点: 线段树套线段树 线段树套平衡 ...

  8. OpenJudge NOI 2.5 1490:A Knight‘s Journey

    [题目链接] OpenJudge NOI 2.5 1490:A Knight's Journey 疑问:题目说可以从任意点出发,以任意点结束.为什么我看他人的代码中,只写从(1,1)出发的情况也能过呢 ...

  9. 深度优先搜索(模板使用)

    深度优先搜索(模板使用) 模板出处 关于模板出处,来自这里 本文仅通过例题对模板的使用进行说明. #include<cstdio> #include<cstring> #inc ...

最新文章

  1. 简单的安卓app小程序代码_开发一款APP大概需要多少钱?
  2. Meta AI推出“杂食者”:一个模型搞定图像、视频和3D数据三大分类任务,性能还不输独立模型...
  3. 从 JavaScript 到 TypeScript 5 - 路由进化
  4. Boost:与gz文件相关的操作实例
  5. 经过 Webpack 处理过的 SAP Spartacus main.js
  6. 小额贷款利息违法吗?
  7. 为什么要使用Entity Framework
  8. 第四章使用jQuery操作DOM元素
  9. websocket连接mysql_websocket 使用 spring 的service层 ,进而调用里面的 dao层 来操作数据库 ,包括redis、mysql等通用...
  10. 基于SignalR的站点有连接数限制问题及解决方案
  11. char*,wchar_t*,CString和BSTR之间的转换
  12. 谈谈JavaScript中的数组、集合及效率
  13. 换个skin,换个心情
  14. 阿里云OSS使用详解(java版本)
  15. 【雅思大作文考官范文】——第五篇: 'literature and history' essay
  16. OpenCore 黑苹果安装教程
  17. [附源码]Python计算机毕业设计服装销售商城系统
  18. items中多个checkgroup在IE6下无法完整显示
  19. pythonista介绍_Pythonista20190405
  20. nginx负载均衡配置及测试

热门文章

  1. 小小的起步VMware vSphere之二
  2. 解决PCoIP连接View 5.0虚拟桌面超时断开导致无法再次登录的问题
  3. JDBC使用总结:增删改查、调用存储过程、执行存储函数、存储过程与存储函数区别分析
  4. PHP 必须勾选用户协议,javascript实现用户必须勾选协议实例讲解
  5. php adodb使用,ADODB类使用_PHP教程
  6. swagger文档配置
  7. 难得一见的DIY针孔相机
  8. 二进制包如何知道go 版本_你有同时使用多版本 Go 语言的需求吗,那就快使用多版本管理利器 GVM 吧!...
  9. thinkphp5 return 返回空_杨丞琳演唱会意外踩空,从两层楼高的舞台掉落,李荣浩心疼发文...
  10. web文件上传(二)--使用form还是ajax