20200718聯考T1 因懶無名
阿新 • • 發佈:2020-07-18
題目描述:
分析:
簽到題想半天,人沒了
將兩個點集合並維護直徑,兩個點集分別的直徑一共四個端點兩兩距離最大即為直徑
區間點集合並,聯想到線段樹,每個區間兩個值表示這個區間點集合並出的端點,簡單維護
考慮顏色變化導致的點集內部插入刪除
加入很好維護,刪除不行
每種顏色動態開點線段樹,依葫蘆畫瓢維護
巨佬們說可以直接一發平衡樹,按顏色排序,支援插入刪除,維護區間直徑
好像Splay和非旋Treap都可以維護
也是可以做的,只不過我平衡樹太菜了,寫的動態開點
我的複雜度是\(O(nlog^2n)\),寫了\(O(1)\)求LCA深度之後就可以減到\(O(nlogn)\)
(怎麼我\(O(nlog^2n)\)
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<set> #include<map> #include<vector> #include<string> #define maxn 200005 #define INF 0x3f3f3f3f using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n,m,Q; int fir[maxn],nxt[maxn<<1],to[maxn<<1],cnt; int sz[maxn],fa[maxn],dpt[maxn],son[maxn],tp[maxn]; int C[maxn],rt[maxn],tot; int lc[maxn<<6],rc[maxn<<6]; inline void newnode(int u,int v) {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} inline void dfs1(int u) { sz[u]=1; for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u]) { fa[to[i]]=u,dpt[to[i]]=dpt[u]+1; dfs1(to[i]),sz[u]+=sz[to[i]]; if(sz[son[u]]<sz[to[i]])son[u]=to[i]; } } inline void dfs2(int u,int ac) { tp[u]=ac;if(son[u])dfs2(son[u],ac); for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u]&&to[i]!=son[u])dfs2(to[i],to[i]); } inline int LCA(int u,int v) { while(tp[u]!=tp[v]) { if(dpt[tp[u]]<dpt[tp[v]])swap(u,v); u=fa[tp[u]]; } return dpt[u]<dpt[v]?u:v; } inline int getdis(int u,int v) {return dpt[u]+dpt[v]-2*dpt[LCA(u,v)];} struct node{ int A,B; inline void pushup(node x,node y) { if(!x.A||!y.A){A=x.A|y.A,B=x.B|y.B;return;} int mx=-1,tmp; if((tmp=getdis(x.A,x.B))>mx)mx=tmp,A=x.A,B=x.B; if((tmp=getdis(y.A,y.B))>mx)mx=tmp,A=y.A,B=y.B; if((tmp=getdis(x.A,y.A))>mx)mx=tmp,A=x.A,B=y.A; if((tmp=getdis(x.A,y.B))>mx)mx=tmp,A=x.A,B=y.B; if((tmp=getdis(x.B,y.A))>mx)mx=tmp,A=x.B,B=y.A; if((tmp=getdis(x.B,y.B))>mx)mx=tmp,A=x.B,B=y.B; } }t[maxn<<2],p[maxn<<6],Ans; inline void insert(int &i,int l,int r,int x,int num) { if(!i)i=++tot; if(l==r){p[i].A=p[i].B=num;return;} int mid=(l+r)>>1; if(x<=mid)insert(lc[i],l,mid,x,num); else insert(rc[i],mid+1,r,x,num); p[i].pushup(p[lc[i]],p[rc[i]]); } inline void build(int i,int l,int r) { if(l==r){t[i]=p[rt[l]];return;} int mid=(l+r)>>1; build(i<<1,l,mid),build(i<<1|1,mid+1,r); t[i].pushup(t[i<<1],t[i<<1|1]); } inline void update(int i,int l,int r,int x) { if(l==r){t[i]=p[rt[x]];return;} int mid=(l+r)>>1; if(x<=mid)update(i<<1,l,mid,x); else update(i<<1|1,mid+1,r,x); t[i].pushup(t[i<<1],t[i<<1|1]); } inline void query(int i,int l,int r,int ql,int qr) { if(qr<l||r<ql)return; if(ql<=l&&r<=qr){Ans.pushup(Ans,t[i]);return;} int mid=(l+r)>>1; query(i<<1,l,mid,ql,qr),query(i<<1|1,mid+1,r,ql,qr); } int main() { n=getint(),m=getint(),Q=getint(); for(int i=1;i<=n;i++)C[i]=getint(); for(int i=1;i<n;i++) { int u=getint(),v=getint(); newnode(u,v),newnode(v,u); } dfs1(1),dfs2(1,1); for(int i=1;i<=n;i++)insert(rt[C[i]],1,n,i,i); build(1,1,m); while(Q--) { int op=getint(),x=getint(),y=getint(); if(op==1) { insert(rt[C[x]],1,n,x,0); update(1,1,m,C[x]); C[x]=y; insert(rt[C[x]],1,n,x,x); update(1,1,m,C[x]); } else { Ans.A=Ans.B=0; query(1,1,m,x,y); printf("%d\n",Ans.A?getdis(Ans.A,Ans.B):0); } } }