来来来权限题但是有入门OJ的传送门
I Think
题意:伟大的树上带修改第k大
思路&实现:对于每个点建一颗权值线段树,维护其到根节点路径上的所有点权。查询(a,b)第k大时先找到lc=Lca(a,b),再用a b树上节点size和-lc与Fa[lc]树上节点size和决定如何左右递归就好。
Attention!
1)局部变量要注意初始化(比如说Query里的tmp)
2)在删除节点调用del(int &rt)不能丢&(类似Swap函数也是)
3)用于离散化的B[]数组,由于可能加入更新的值,所以大小要开得比N大
4)计算Lca时,u和v的判等需要放在前面的if外,因为题目并没有说不能查询两个相同的点。
鉴于以上错误,成功刷新了自己的调题时间记录……
先上一份会TLE的代码,准备有时间再打一份只有修改值使用树状数组结合的。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lowbit(x) x&(-x)
using namespace std;
template <typename T> void read(T &x) {
T f=1;x=0; char ch=getchar();
while(ch>'9'||ch<'0') { if(ch=='-') f=-1;ch=getchar(); }
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=f;
}
const int sm = 8e4+5;
const int sn = sm*300;
int N,Q,tot,cnt;
int A[sm],B[sm<<1],C[sn],Ls[sn],Rs[sn];
int Lt[sm],Rt[sm],dep[sm],Fa[sm][20];
int hd[sm<<1],to[sm<<1],nxt[sm<<1];
struct query {
int x,y,z;
}q[sm];
void Swap(int &x,int &y) { int t=x;x=y;y=t; }
void add(int f,int t) {
to[++tot]=t,nxt[tot]=hd[f],hd[f]=tot;
to[++tot]=f,nxt[tot]=hd[t],hd[t]=tot;
}
int Hash(int x) {
return lower_bound(B+1,B+cnt+1,x)-B;
}
void Insert(int &rt,int l,int r,int p,int val) {
if(!rt) rt=++tot; C[rt]+=val;
if(l==r) return ;
int m=(l+r)>>1;
if(p<=m) Insert(Ls[rt],l,m,p,val);
else Insert(Rs[rt],m+1,r,p,val);
}
void Dfs(int x,int f) {
dep[x]=dep[Fa[x][0]=f]+1,Lt[x]=++tot;
for(int i=1;i<20;++i)
Fa[x][i]=Fa[Fa[x][i-1]][i-1];
for(int i=hd[x];i;i=nxt[i])
if(to[i]!=f) Dfs(to[i],x);
Rt[x]=tot;
}
int Lca(int u,int v) {
if(dep[u]!=dep[v]) {
if(dep[u]<dep[v])Swap(u,v);
for(int i=19;i>=0;--i)
if(dep[Fa[u][i]]>dep[v]) u=Fa[u][i];
u=Fa[u][0];
}
if(u==v) return u;
for(int i=19;i>=0;--i)
if(Fa[u][i]!=Fa[v][i]) u=Fa[u][i],v=Fa[v][i];
return Fa[u][0];
}
struct BIT {
int root[sn];
BIT() { memset(root,0,sizeof(root)); }
void Modify(int x,int p,int val) {
for(int i=x;i<=N;i+=lowbit(i))
Insert(root[i],1,cnt,p,val);
}
void Add(int l,int r,int p,int val) {
Modify(l,p,val),Modify(r+1,p,-val);
}
void Query(int k,int a,int b) {
int lc=Lca(a,b),l=1,r=cnt,m;
int rt[4][30],n[4]={0,0,0,0},flag[4]={1,1,-1,-1};
int pos[4]={Lt[a],Lt[b],Lt[lc],Lt[Fa[lc][0]]};
if(dep[a]+dep[b]-dep[lc]-dep[Fa[lc][0]]<k)
puts("invalid request!");
else {
for(int i=0;i<4;++i)
for(int j=pos[i];j;j-=lowbit(j))
rt[i][++n[i]]=root[j];
while(l<r) {
int tmp=0;m=(l+r)>>1;
for(int i=0;i<4;++i)
for(int j=1;j<=n[i];++j)
if(rt[i][j]) tmp+=C[Rs[rt[i][j]]]*flag[i];
if(k<=tmp) {
l=m+1;
for(int i=0;i<4;++i)
for(int j=1;j<=n[i];++j)
if(rt[i][j])rt[i][j]=Rs[rt[i][j]];
} else {
r=m,k-=tmp;
for(int i=0;i<4;++i)
for(int j=1;j<=n[i];++j)
if(rt[i][j])rt[i][j]=Ls[rt[i][j]];
}
}
printf("%d\n",B[l]);
}
}
}tree;
int main() {
read(N),read(Q);
for(int i=1;i<=N;++i) read(A[i]),B[++cnt]=A[i];
for(int i=1,x,y,z;i<N;++i) read(x),read(y),add(x,y);
tot=0,Dfs(1,0),tot=0;
for(int i=1;i<=Q;++i) {
read(q[i].x),read(q[i].y),read(q[i].z);
if(!q[i].x) B[++cnt]=q[i].z;
}
sort(B+1,B+cnt+1);
cnt=unique(B+1,B+cnt+1)-B-1;
for(int i=1;i<=N;++i)
tree.Add(Lt[i],Rt[i],Hash(A[i]),1);
for(int i=1;i<=Q;++i)
if(!q[i].x) {
tree.Add(Lt[q[i].y],Rt[q[i].y],Hash(A[q[i].y]),-1);
tree.Add(Lt[q[i].y],Rt[q[i].y],Hash(q[i].z),1);
A[q[i].y]=q[i].z;
}
else tree.Query(q[i].x,q[i].y,q[i].z);
return 0;
}
来一份AC代码~
#include<cstdio>
#include<algorithm>
#define lowbit(x) x&(-x)
const int sm = 8e4+5;
const int Sn = sm*128;
int N,Q,tot,cnt,ss;
int C[Sn],Rs[Sn],Ls[Sn];
int A[sm],B[sm<<1],St[sm],Rt[sm];
int to[sm<<1],nxt[sm<<1],hd[sm];
int Fa[sm],tp[sm],sn[sm],sz[sm],dp[sm],pl[sm],en[sm];
struct Que {
int k,a,b;
}q[sm];
namespace Tree {
int use[4][sm];
template <typename T> void read(T &x) {
char ch=getchar();x=0;int f=1;
while(ch>'9'||ch<'0') { if(ch=='-')f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
x*=f;
}
void Add(int u,int v) {
to[++tot]=v,nxt[tot]=hd[u],hd[u]=tot;
to[++tot]=u,nxt[tot]=hd[v],hd[v]=tot;
}
void Swap(int &x,int &y) { int t=x;x=y;y=t; }
int Hash(int x) { return std::lower_bound(B+1,B+cnt+1,x)-B; }
int Insert(int pre,int l,int r,int p,int val) {
int cur=++tot; C[cur]=C[pre]+val;
if(l==r) return cur; int m=(l+r)>>1;
if(p<=m) Ls[cur]=Insert(Ls[pre],l,m,p,val),Rs[cur]=Rs[pre];
if(p >m) Rs[cur]=Insert(Rs[pre],m+1,r,p,val),Ls[cur]=Ls[pre];
return cur;
}
void Dfsa(int x,int fa) {
dp[x]=dp[fa]+1,Fa[x]=fa;
sn[x]=0,sz[x]=1;
Rt[x]=Insert(Rt[fa],1,cnt,Hash(A[x]),1);
for(int i=hd[x];i;i=nxt[i])
if(to[i]!=fa) {
Dfsa(to[i],x);
sz[x]+=sz[to[i]];
if(sz[to[i]]>sz[sn[x]])
sn[x]=to[i];
}
}
void Dfsb(int x,int top) {
tp[x]=top,pl[x]=++ss;
if(sn[x]) Dfsb(sn[x],top);
for(int i=hd[x];i;i=nxt[i])
if(to[i]!=Fa[x]&&to[i]!=sn[x])
Dfsb(to[i],to[i]);
en[x]=ss;
}
int Lca(int u,int v) {
while(tp[u]!=tp[v]){
if(dp[tp[u]]<dp[tp[v]])Swap(u,v);
u=Fa[tp[u]];
}
if(dp[u]>dp[v])Swap(u,v);
return u;
}
void TModify(int u,int v,int p,int val) {
for(int i=u;i<=N;i+=lowbit(i))
St[i]=Insert(St[i],1,cnt,p,val);
for(int i=v;i<=N;i+=lowbit(i))
St[i]=Insert(St[i],1,cnt,p,-val);
}
int Sum(int x,int y) {
int res=0;
for(int i=1;i<=y;++i)
res+=C[Rs[use[x][i]]];
return res;
}
void RQuery(int a,int b,int K) {
int l=1,r=cnt,Lc=Lca(a,b),Gc=Fa[Lc];
if(dp[a]+dp[b]-dp[Lc]-dp[Gc]<K) { printf("invalid request!\n"); return ; }
int ct[4]={0,0,0,0},tmp[4]={pl[a],pl[b],pl[Lc],pl[Gc]};
for(int i=0;i<4;++i)
for(int j=tmp[i];j;j-=lowbit(j))
use[i][++ct[i]]=St[j];
a=Rt[a],b=Rt[b],Lc=Rt[Lc],Gc=Rt[Gc];
while(l<r) {
int m=(l+r)>>1,tmp;
tmp=C[Rs[a]]+C[Rs[b]]+Sum(0,ct[0])+Sum(1,ct[1])-C[Rs[Lc]]-C[Rs[Gc]]-Sum(2,ct[2])-Sum(3,ct[3]);
if(tmp<K) {
K-=tmp,r=m; a=Ls[a],b=Ls[b],Lc=Ls[Lc],Gc=Ls[Gc];
for(int i=0;i<4;++i)
for(int j=1;j<=ct[i];++j)
use[i][j]=Ls[use[i][j]];
}
else {
a=Rs[a],b=Rs[b],Lc=Rs[Lc],Gc=Rs[Gc],l=m+1;
for(int i=0;i<4;++i)
for(int j=1;j<=ct[i];++j)
use[i][j]=Rs[use[i][j]];
}
}
printf("%d\n",B[l]);
}
}
int main() {
using namespace Tree;
read(N),read(Q);
for(int i=1;i<=N;++i) read(A[i]),B[++cnt]=A[i];
for(int i=1,u,v;i< N;++i)
read(u),read(v),Add(u,v);
for(int i=1;i<=Q;++i) {
read(q[i].k),read(q[i].a),read(q[i].b);
if(!q[i].k) B[++cnt]=q[i].b;
}
std::sort(B+1,B+cnt+1);
cnt=std::unique(B+1,B+cnt+1)-B-1;
tot=0,Dfsa(1,0),Dfsb(1,1);
for(int i=1;i<=Q;++i) {
if(q[i].k) RQuery(q[i].a,q[i].b,q[i].k);
if(!q[i].k) {
TModify(pl[q[i].a],en[q[i].a]+1,Hash(A[q[i].a]),-1);
TModify(pl[q[i].a],en[q[i].a]+1,Hash(A[q[i].a]=q[i].b),1);
}
}
return 0;
}