首先大概有一个树剖+树套树的做法,但我哪会写啊

然后发现k很小,如果用线段树记每个区间前k大的的话,可以O(k)地合并

而且一个点还有可能有好多个骑士,所以要用multiset维护一下

然后树剖就好啦

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
#define IT multiset<int>::iterator
using namespace std;
typedef long long ll;
const int maxn=4e4+,maxk=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int eg[maxn*][],egh[maxn],ect,smr[maxn][];
int N,M,Q,K;
int wson[maxn],dfn[maxn],dep[maxn],siz[maxn],top[maxn],fa[maxn],tot;
int fr[maxn*][maxk],id[maxn],ans[maxk],tmp[maxk];
multiset<int,greater<int> > st[maxn]; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
} void dfs1(int x){
siz[x]=;int mm=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];
if(b==fa[x]) continue;
fa[b]=x;dep[b]=dep[x]+;
dfs1(b);siz[x]+=siz[b];
if(siz[b]>mm) mm=siz[b],wson[x]=b;
}
}
void dfs2(int x){
dfn[x]=++tot;id[tot]=x;
top[x]=(x==wson[fa[x]]?top[fa[x]]:x);
if(wson[x]) dfs2(wson[x]);
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];
if(b==wson[x]||b==fa[x]) continue;
dfs2(b);
}
} inline void update(int p){
int l=p<<,r=p<<|;
int a=,b=,i=;
for(;a<=fr[l][]&&i<K;a++){
for(;b<=fr[r][]&&fr[r][b]>fr[l][a]&&i<K;b++)
fr[p][++i]=fr[r][b];
if(i<K) fr[p][++i]=fr[l][a];
}for(;b<=fr[r][]&&i<K;b++) fr[p][++i]=fr[r][b];
fr[p][]=i;
} void build(int p,int l,int r){
if(l==r){
int i=;
for(IT it=st[id[l]].begin();i<K&&it!=st[id[l]].end();it++){
fr[p][++i]=*it;
}fr[p][]=i;
}else{
int m=l+r>>;
build(p<<,l,m);build(p<<|,m+,r);
update(p);
}
} void query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y){
if(!ans[]){
memcpy(ans,fr[p],sizeof(ans));
return;
}
int a=,b=,i=;
for(;a<=fr[p][]&&i<K;a++){
for(;b<=ans[]&&ans[b]>fr[p][a]&&i<K;b++)
tmp[++i]=ans[b];
if(i<K) tmp[++i]=fr[p][a];
}for(;b<=ans[]&&i<K;b++) tmp[++i]=ans[b];
tmp[]=i;
memcpy(ans,tmp,sizeof(ans));
}else{
int m=l+r>>;
if(x<=m) query(p<<,l,m,x,y);
if(y>=m+) query(p<<|,m+,r,x,y);
}
} void change(int p,int l,int r,int x,int y,bool b){
if(l==r){
if(!b) st[id[l]].erase(st[id[l]].find(y));
else st[id[l]].insert(y);
int i=;
for(IT it=st[id[l]].begin();i<K&&it!=st[id[l]].end();it++){
fr[p][++i]=*it;
}fr[p][]=i;
}else{
int m=l+r>>;
if(x<=m) change(p<<,l,m,x,y,b);
else change(p<<|,m+,r,x,y,b);
update(p);
}
} void solve1(int x,int y){
ans[]=,tmp[]=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
query(,,N,dfn[top[x]],dfn[x]);
// printf("%d %d\n",dfn[top[x]],x);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
query(,,N,dfn[y],dfn[x]);
} void solve2(int x,int y){
change(,,N,dfn[smr[x][]],smr[x][],);
change(,,N,dfn[y],smr[x][],);
smr[x][]=y;
}
void solve3(int x,int y){
change(,,N,dfn[smr[x][]],smr[x][],);
change(,,N,dfn[smr[x][]],y,);
smr[x][]=y;
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}
M=rd();
for(i=;i<=M;i++){
smr[i][]=rd(),smr[i][]=rd();
st[smr[i][]].insert(smr[i][]);
}
Q=rd(),K=rd();
dep[]=;dfs1();
dfs2();build(,,N);
for(j=;j<=Q;j++){
int a=rd(),b=rd(),c=rd();
if(a==){
solve1(b,c);
if(ans[]==) printf("-1");
for(i=;i<=ans[];i++)
printf("%d ",ans[i]);
printf("\n");
}else if(a==) solve2(b,c);
else solve3(b,c);
}
return ;
}

bzoj4336 骑士的旅行 (树链剖分+multiset)的更多相关文章

  1. [BZOj4336][BJOI2015]骑士的旅行(树链剖分+线段树)

    树链剖分,对每个叶子用multiset记录前K大士兵,其余节点通过从儿子归并维护前K大士兵.过于模板. #include<set> #include<cstdio> #incl ...

  2. CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...

  3. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  4. BZOJ3531:[SDOI2014]旅行(树链剖分)

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  5. P3313 [SDOI2014]旅行——树链剖分+线段树(动态开点?)

    P3313 [SDOI2014]旅行 一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和: 树链剖分把树变成链: 把每个宗教单开一个线段树,维护区间总和和最大值: 宗教很多,需要动态 ...

  6. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  7. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

  8. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  9. BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...

随机推荐

  1. Codeforces 987E Petr and Permutations(数组的置换与复原 、结论)

    题目连接: Petr and Permutations 题意:给出一个1到n的序列,Petr打乱了3n次,Um_nik打乱了7n+1次,现在给出被打乱后的序列,求是谁打乱的. 题解:因为给出了一个3* ...

  2. EF5.0区别于EF4.0的crud区别

    public T AddEntity(T entity) { //EF4.0的写法 添加实体 //db.CreateObjectSet<T>().AddObject(entity); // ...

  3. Mvc_model实体数据验证

    MVC提供了很方便的数据验证,只需要在model里加入相关的正则等,那么就会在前台里生成相关的验证脚本.需要引用两个js文件: jquery.validate.min.js jquery.valida ...

  4. 个人对vuex的表象理解(笔记)

    一个东西,首先要知道为什么用它,为什么要vuex,官方解释为了解决繁杂事件订阅和广播,那么事件的$dispatch,$on,怎么就复杂了?许多人是不是感觉后者还挺简单的,对的 如果简单小型项目,那么不 ...

  5. 12.16 Daily Scrum

      Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表.             邓亚梅             美化搜索框UI. 美 ...

  6. sqoop 使用笔记

    好久没有更新自己技术博客,现在开始工作了,把自己遇到的问题写到这里边来 主要把自己的问题写出来,分享给大家 sqoop 导入数据时候 有时候会遇到mysql 中有sql 中的关键字 这时候如果直接导出 ...

  7. Quartz.NET 入门,带C#实例

    概述 Quartz.NET是一个开源的作业调度框架,非常适合在平时的工作中,定时轮询数据库同步,定时邮件通知,定时处理数据等. Quartz.NET允许开发人员根据时间间隔(或天)来调度作业.它实现了 ...

  8. Oracle数据库SQLPLUS 连接显示 ??? 的解决

    linux下 安装了中文版本的,造成sqlplus 连接时出现了乱码 如图 一开始以为是LANG 变量的问题 后来发现是NLS_LANG的问题 解决方法: export NLS_LANG=" ...

  9. ViewDragHelper

    参考:Android 之 ViewDragHelper 详解   Android 之 ViewDragHelper详解(二) 看了几篇博客,并参考了上面的两篇博客,整理一下ViewDragHelper ...

  10. bat脚本的写法

    当你每次都要输入相同的命令时,可以把这么多命令存为一个批处理,从此以后,只要运行这个批处理,就相当于打了几行.几十行命令.下面以Nginx服务的停止脚本为例写一个bat批处理文件: 1.新建nginx ...