19-10-19-I
中午考试困够呛。
T1
我想打矩阵快速幂,然后我咕了
T2
打T1了所以又咕了。
T3
每一个黑点更新答案只有两种方式:
- 更新子树。
- 更新父链上的兄弟,叔伯,……
于是:
把树拍在$DFS$序上。
更新子树,区间修改。
更新父链,就需要用$DFS$序的拆分,修改两个部分。
#include <iostream> #include <cstring> #include <cstdio> #define N 111111 #define lc(k) (k<<1) #define rc(k) (k<<1|1) using namespace std; struct SR{ int next,t; }rs[N*2]; int fl[N],cnt=0; struct XDS{ int l,r; int dat,lz; }rt[4*N]; int fir[N],las[N],wi[N]; int dfsxu[2*N]; int dfcnt=0; int fa[N],pn,qn; bool is_v[N]; void add(int f,int t){ rs[cnt].t=t; rs[cnt].next=fl[f]; fl[f]=cnt++; } void build(int k,int l,int r){ // cout<<k<<" "<<l<<" "<<r<<endl; rt[k].l=l,rt[k].r=r; rt[k].dat=0; if(l==r)return ; int mid=(l+r)/2; build(lc(k),l ,mid); build(rc(k),mid+1,r ); } void downlz(int k){ if(rt[k].l!=rt[k].r && rt[k].lz!=0){ int val=rt[k].lz; rt[lc(k)].lz=max(rt[lc(k)].lz,val); rt[rc(k)].lz=max(rt[rc(k)].lz,val); rt[lc(k)].dat=max(rt[lc(k)].dat,val); rt[rc(k)].dat=max(rt[rc(k)].dat,val); rt[k].lz=0; } } void change(int k,int l,int r,int v){ if(l>r)return ; downlz(k); if(l<=rt[k].l && rt[k].r<=r){ rt[k].lz=v; rt[k].dat=max(rt[k].dat,v); return ; } int mid=(rt[k].l+rt[k].r)/2; if(mid>=l) change(lc(k),l,r,v); if(mid<r) change(rc(k),l,r,v); rt[k].dat=max(rt[lc(k)].dat,rt[rc(k)].dat); } int query(int k,int l,int r){ if(l>r)return 0; int ans=0; downlz(k); if(l<=rt[k].l && rt[k].r<=r) return rt[k].dat; int mid=(rt[k].l+rt[k].r)/2; if(mid>=l) ans=max(ans,query(lc(k),l,r)); if(mid<r) ans=max(ans,query(rc(k),l,r)); return ans; } void dfs(int k,int pre){ dfcnt++; dfsxu[dfcnt]=k; fir[k]=dfcnt; for(int i=fl[k];i!=-1;i=rs[i].next){ int t=rs[i].t; if(t!=pre){ fa[t]=k; dfs(t,k); } } dfcnt++; dfsxu[dfcnt]=k; las[k]=dfcnt; } int main(){ // freopen("lca3.in","r",stdin);\ freopen("1.out","w",stdout); int a,b; char st[10]; memset(fl,-1,sizeof fl); scanf("%d%d",&pn,&qn); for(int i=1;i<=pn;i++) scanf("%d",wi+i); for(int i=1;i<pn;i++){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1,0); // for(int i=1;i<=pn*2;i++)\ cout<<dfsxu[i]<<" ";\ cout<<endl; build(1,1,pn*2); for(int i=1;i<=qn;i++){ scanf("%s%d",st,&a); if(st[0]=='M'){ change(1,fir[a],las[a],wi[a]); // cout<<fir[a]<<"="<<las[a]<<endl; while(fa[a]!=0){ // cout<<"A:"<<a<<" FAA:"<<fa[a]<<" wi:"<<wi[fa[a]]<<endl; change(1,fir[fa[a]],fir[a]-1,wi[fa[a]]); // cout<<fir[fa[a]]<<" "<<fir[a]-1<<endl; change(1,las[a]+1,las[fa[a]],wi[fa[a]]); // cout<<las[a]+1<<" "<<las[fa[a]]-1<<endl; if(is_v[a])break; is_v[a]=1; a=fa[a]; } } else { int ans=query(1,fir[a],fir[a]); printf("%d\n",ans==0?-1:ans); } } }
Miemeng真的蒻