Write a summary of the learning content of the last three days ...
Actually I feel that I can finish it in one day, but recently I have to take liver culture class
\ (1. \) Chairman tree \ (\ rightarrow \) section \ (k \) is the largest, or the relevant content of the line tree can be persisted
\ (2. \) The tree chain is the largest \ (k \)
\ (3. \) is the largest with repair interval \ (k \)
\ (4. \) with repair tree chain \ (k \) large
The last two are actually tree sets (tree-like array set of chairman trees)
principle
Our principle is to use the chairman tree to maintain the prefix and
Now we have a modification operation. If we simply modify the \ (n \) prefix chairman tree, query the prefix and
The complexity is too high, which is unacceptable to us
Then we consider turning to maintaining the position of the chairman tree with a tree-like array, and maintaining and modifying and querying on the marker
In this way, the complexity is \ (O (nlog ^ 2n) \) every time we modify , the query is the same
Attach a series of practices on the tree:
Similar to \ (p = rt [i], pre = rt [i-1] \) on the interval
Here we replace: \ (p = rt [x], pre = rt [fa [x]] \)
Just update it as before, then here is the difference on the tree when querying
Don't be dizzy, every tree here is a weighted line segment tree
int lca=lca(x,y)'s node ,f_l=fa[lca(x,y)]'s node
sum=val(ls[x])+val(ls[y])-val(lca)-val(ls(f_l))
Pseudo code
Then for this big board with repair tree chain \ (k \) : P4175 [CTSC2008] network management
Found that the modification of each point has an impact on the subtree
So this is an interval change, single check
Difference! It becomes an interval check, single point plus
Then maintain a \ (dfn \) sequence on the tree array \ (OK \)
This is quite understandable, but the size of the hand, the hand is not easy to adjust (the blogger has not adjusted the hand too long this time)
In fact: we can learn the writing of this big guy while jumping \ (ls \) or \ (rs \) , which can reduce the amount of code:
https://www.luogu.com.cn/blog/jiqimao/p4175-ti-xie
After I finished writing, I found that there is still a way to write structure.
Finally put the stinky and long \ (Code: \)
#include<bits/stdc++.h>
using namespace std;
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=80000+10;
inline int lowbit(int x){return x&(-x);}
vector<int> g[N];
int fa[N][20],lg[N],dep[N],b[N<<1],m,T,in[N],out[N];
struct node{
int id,k,x,y,val,opt;
}q[N];
int c1,c2,c3,c4,t1[30],tim,t2[30],t3[30],t4[30],n,p[N];
struct tree{
int ls,rs,val;
#define ls(p) t[p].ls
#define rs(p) t[p].rs
#define val(p) t[p].val
}t[20000010];
int rt[N<<2],tot;
inline void push_up(int p){return val(p)=val(ls(p))+val(rs(p)),void();}
inline void update(int &p,int l,int r,int x,int v)
{
if(!p) p=++tot;
if(l==r) return val(p)+=v,void();
int mid=(l+r)>>1;
if(x<=mid) update(ls(p),l,mid,x,v);
else update(rs(p),mid+1,r,x,v);
return push_up(p);
}
inline int query(int l,int r,int k)
{
if(l==r) return l;
int mid=(l+r)>>1,sum=0;
for(int i=1;i<=c3;++i) sum+=val(rs(t3[i]));
for(int i=1;i<=c4;++i) sum+=val(rs(t4[i]));
for(int i=1;i<=c2;++i) sum-=val(rs(t2[i]));
for(int i=1;i<=c1;++i) sum-=val(rs(t1[i]));
if(k>sum)
{
for(int i=1;i<=c1;++i) t1[i]=ls(t1[i]);
for(int i=1;i<=c2;++i) t2[i]=ls(t2[i]);
for(int i=1;i<=c3;++i) t3[i]=ls(t3[i]);
for(int i=1;i<=c4;++i) t4[i]=ls(t4[i]);
return query(l,mid,k-sum);
}
else
{
for(int i=1;i<=c1;++i) t1[i]=rs(t1[i]);
for(int i=1;i<=c2;++i) t2[i]=rs(t2[i]);
for(int i=1;i<=c3;++i) t3[i]=rs(t3[i]);
for(int i=1;i<=c4;++i) t4[i]=rs(t4[i]);
return query(mid+1,r,k);
}
}
inline int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1];
if(x==y) return x;
for(int i=19;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
inline int ask(int x,int y,int k)
{
c1=0,c2=0,c3=0,c4=0;
int l=lca(x,y);
for(int i=in[fa[l][0]];i;i-=lowbit(i)) t1[++c1]=rt[i];
for(int i=in[l];i;i-=lowbit(i)) t2[++c2]=rt[i];
for(int i=in[x];i;i-=lowbit(i)) t3[++c3]=rt[i];
for(int i=in[y];i;i-=lowbit(i)) t4[++c4]=rt[i];
return query(1,m,k);
}
inline void dfs(int x,int fat)
{
dep[x]=dep[fat]+1; fa[x][0]=fat; in[x]=++tim;
for(int i=1;(1<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1];
int siz=g[x].size();
for(int i=0;i<siz;++i) if(g[x][i]!=fat) dfs(g[x][i],x);
return out[x]=tim,void();
}
inline void change(int x,int pos,int val)
{
for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],1,m,pos,val);
return ;
}
signed main()
{
for(int i=1;i<N;++i) lg[i]=lg[i-1]+((1<<lg[i-1])==i);
n=read(); T=read();
for(int i=1;i<=n;++i) p[i]=read(),b[++m]=p[i];
for(int i=1;i<n;++i)
{
int u=read(),v=read();
g[u].push_back(v); g[v].push_back(u);
}
for(int i=1;i<=T;++i)
{
q[i].opt=read();
if(q[i].opt) q[i].x=read(),q[i].y=read(),q[i].k=q[i].opt;
else q[i].id=read(),q[i].val=read(),b[++m]=q[i].val;
}
sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1;
for(int i=1;i<=n;++i) p[i]=lower_bound(b+1,b+m+1,p[i])-b;
for(int i=1;i<=T;++i) if(!q[i].opt) q[i].val=lower_bound(b+1,b+m+1,q[i].val)-b;
dfs(1,0);
for(int i=1;i<=n;++i) change(in[i],p[i],1),change(out[i]+1,p[i],-1);
for(int i=1;i<=T;++i)
{
if(q[i].opt)
{
int l=lca(q[i].x,q[i].y);
if(dep[q[i].x]+dep[q[i].y]-dep[l]*2+1<q[i].k) puts("invalid request!");
else printf("%d\n",b[ask(q[i].x,q[i].y,q[i].k)]);
}
else
{
change(in[q[i].id],p[q[i].id],-1),change(out[q[i].id]+1,p[q[i].id],1);
p[q[i].id]=q[i].val;
change(in[q[i].id],p[q[i].id],1); change(out[q[i].id]+1,p[q[i].id],-1);
}
}
return 0;
}
}
signed main(){return yspm::main();}
It ’s because it ’s all a board, so I learned this. The line tree set balance tree does n’t work. \ (2444 \)