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

然后发现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. @Vue/Cli 3 关于 render 空的处理

    问题场景 vue-cli 3 在打包部署时候会出现 dist folder not working "Uncaught TypeError: Cannot set property 'ren ...

  2. myeclipse、maven、tomcat、jdk技巧和坑【待完善】

    公司使用前后不分离或半分离的springmvc + maven ,自己不得不研究研究myeclipse.maven.tomcat等等 开发环境搭建:坑一: Unable to process Jar ...

  3. 如何解决jersey框架中以json格式返回数组,当数组中元素一个时json格式不对

    原文地址:http://www.cnblogs.com/swpk/p/3566536.html?utm_source=tuicool jersey 是oracle 出的一个较好的REST框架.使用此框 ...

  4. Redis常用操作--------SortedSet(有序集合)

    1.ZADD key score member [[score member] [score member] ...] 将一个或多个 member 元素及其 score 值加入到有序集 key 当中. ...

  5. c++ 中关于一些变量不能声明的问题

    j0,j1,jn,y0,y1,yn被c++中某些函数占用了,所以是不能被声明的,今天就遇到了这个问题,结果我在自己写的程序中找了半天都没找到重复申明的y1

  6. 对于VS软件的个人评价

    因为还是一个菜鸟,对于VS这样的大软件还只能是自己个人的理解,以前用的是VC++,后来因为电脑系统更新,开始接触了VS,个人觉得还是vs2010更好用一些,作为一款windows平台应用程序的集成开发 ...

  7. 《Linux内核分析》读书笔记(四章)

    <Linux内核分析>读书笔记(四章) 标签(空格分隔): 20135328陈都 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行 ...

  8. PAT 1023 组个最小数

    https://pintia.cn/problem-sets/994805260223102976/problems/994805298269634560 给定数字0-9各若干个.你可以以任意顺序排列 ...

  9. PAT 1061 判断题

    https://pintia.cn/problem-sets/994805260223102976/problems/994805268817231872 判断题的评判很简单,本题就要求你写个简单的程 ...

  10. HTML的input类型为hidden导致无法reset改字段的value问题

    问题关键:根据HTML规范,hidden是非ui类元素,不接受用户处理.所以form的 reset并不影响它. http://stackoverflow.com/questions/6367793/w ...