Link
Difficulty
算法难度5,思维难度4,代码难度6
Description
给你一棵树,再给你一堆骑士,每个骑士有居住地和武力值
有3种操作:
- 查询x到y的路上,前K大的骑士的武力值
- 修改第i个骑士的居住地
- 修改第i个骑士的武力值
1 ≤ n ≤ 4 ∗ 1 0 4 , 1 ≤ K ≤ 20 1\le n\le 4*10^4,1\le K\le 20 1≤n≤4∗104,1≤K≤20
Solution
看K这么小,直接暴力树剖线段树维护咯
就维护线段树上每个点的前K大
然后树上每个点存这个点的所有的骑士
存的时候就用multiset就好了,注意删除
时间复杂度 O ( n k l o g 2 n ) O(nklog^2n) O(nklog2n)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f==1?x:-x;
}
const int N=1e5+5;
int n,m,q,k,tot;
int head[N],to[N],Next[N];
inline void addedge(int x,int y){
to[++tot]=y;
Next[tot]=head[x];
head[x]=tot;
}
int size[N],heavy[N],top[N],father[N],dfn[N],dfn_clock,dep[N];
inline void dfs(int x,int fa){
size[x]=1;father[x]=fa;dep[x]=dep[fa]+1;
for(int i=head[x];i;i=Next[i]){
int u=to[i];
if(u==fa)continue;
dfs(u,x);
size[x]+=size[u];
if(size[u]>size[heavy[x]])heavy[x]=u;
}
}
inline void dfs2(int x,int first){
top[x]=first;
dfn[x]=++dfn_clock;
if(size[x]==1)return;
dfs2(heavy[x],first);
for(int i=head[x];i;i=Next[i]){
int u=to[i];
if(u==father[x] || u==heavy[x])continue;
dfs2(u,u);
}
}
struct data{
int len,a[21];
data(){len=0;memset(a,0,sizeof a);}
inline data operator + (const data& b) const {
data ans;
ans.len=min(k,len+b.len);
for(int i=1,j=1,k=1;i<=ans.len;++i){
if(j<=len && k<=b.len && a[j]>=b.a[k]){
ans.a[i]=a[j];
++j;
}
else if(j<=len && k<=b.len && b.a[k]>a[j]){
ans.a[i]=b.a[k];
++k;
}
else{
if(j<=len){
ans.a[i]=a[j];
++j;
}
else{
ans.a[i]=b.a[k];
++k;
}
}
}
return ans;
}
}d[N<<2];
multiset<int,greater<int> > s[N<<2];
int type;
inline void pushup(int rt){
d[rt]=d[rt<<1]+d[rt<<1|1];
}
inline void insert(int rt,int l,int r,int pos,int v){
if(l==r){
if(type==1)s[rt].insert(v);
else s[rt].erase(s[rt].lower_bound(v));
d[rt].len=min(k,(int)s[rt].size());
memset(d[rt].a,0,sizeof d[rt].a);
int i=1;
for(multiset<int>::iterator it=s[rt].begin();it!=s[rt].end();++it){
d[rt].a[i]=*it;
if(i==d[rt].len)break;
++i;
}
return;
}
int mid=(l+r)>>1;
if(pos<=mid)insert(rt<<1,l,mid,pos,v);
else insert(rt<<1|1,mid+1,r,pos,v);
pushup(rt);
}
inline data query(int rt,int l,int r,int L,int R){
if(L<=l && r<=R)return d[rt];
int mid=(l+r)>>1;
if(L<=mid && mid+1<=R)return query(rt<<1,l,mid,L,R)+query(rt<<1|1,mid+1,r,L,R);
else if(L<=mid)return query(rt<<1,l,mid,L,R);
else return query(rt<<1|1,mid+1,r,L,R);
}
inline data Query(int x,int y){
data ans;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=ans+query(1,1,n,dfn[top[x]],dfn[x]);
x=father[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=ans+query(1,1,n,dfn[y],dfn[x]);
return ans;
}
int V[N],X[N];
int main(){
n=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
addedge(x,y);addedge(y,x);
}
dfs(1,0);
dfs2(1,1);
m=read();
for(int i=1;i<=m;++i){
V[i]=read();X[i]=read();
}
q=read();k=read();
for(int i=1;i<=m;++i){
type=1;insert(1,1,n,dfn[X[i]],V[i]);
}
for(int i=1;i<=q;++i){
int opt=read(),x=read(),y=read();
if(opt==1){
data ans=Query(x,y);
if(ans.len==0)printf("-1\n");
else{
for(int i=1;i<=ans.len;++i)printf("%d ",ans.a[i]);
putchar('\n');
}
}
else if(opt==2){
type=2;insert(1,1,n,dfn[X[x]],V[x]);
X[x]=y;
type=1;insert(1,1,n,dfn[X[x]],V[x]);
}
else{
type=2;insert(1,1,n,dfn[X[x]],V[x]);
V[x]=y;
type=1;insert(1,1,n,dfn[X[x]],V[x]);
}
}
return 0;
}