SPOJ QTREE4 Query on a tree IV ——动态点分治
【题目分析】
同bzoj1095
然后WA掉了。
发现有负权边,只好把rmq的方式改掉。
然后T了。
需要进行底(ka)层(chang)优(shu)化。
然后还是T
下午又交就A了。
【代码】
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxe 200005 #define maxn 100005 #define inf (0x3f3f3f3f) #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) int h[maxe],to[maxe],ne[maxe],en=0,ban[maxn],n,m,rt,now,dst[maxn],Tree_rt,col[maxn],ans=-1,x,aim; int b[maxn<<2],cnt=0,tag=0,pos[maxn],c[maxn<<2][20],_log[maxn<<2],w[maxe],d[maxn<<2][20],dep[maxn]; void add(int a,int b,int c) {to[en]=b;ne[en]=h[a];w[en]=c;h[a]=en++;} struct Heap{ priority_queue <int> heap,del; void Ins(int x){heap.push(x);} void Del(int x){del.push(x);} void Pop(){while (del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); heap.pop();} int Top(){while (del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); return heap.top();} int S_Top(){int tmp=Top(),ret;Pop();ret=Top();Ins(tmp);return ret; } int Size(){return heap.size()-del.size();} }s1[maxn],s2[maxn],lst; int mx[maxn],siz[maxn],size,fa[maxn]; char opt[11]; void dfs(int o,int fa) { if (!tag)b[++cnt]=o,pos[o]=cnt; siz[o]=1;mx[o]=0; for (int i=h[o];i>=0;i=ne[i]) if (!ban[to[i]]&&to[i]!=fa) { if (!tag) dep[to[i]]=dep[o]+1; dfs(to[i],o); if (!tag) b[++cnt]=o; siz[o]+=siz[to[i]]; if (siz[to[i]]>mx[o]) mx[o]=siz[to[i]]; } } void dfs_rt(int o,int fa) { if (max(mx[o],size-siz[o])<now) rt=o,now=max(mx[o],size-siz[o]); for (int i=h[o];i>=0;i=ne[i]) if (!ban[to[i]]&&to[i]!=fa) dfs_rt(to[i],o); } int lca(int a,int b) { int pa=pos[a],pb=pos[b]; if (pa>pb) swap(pa,pb); int l=_log[pb-pa+1]; if (dep[d[pa][l]]<dep[d[pb-(1<<l)+1][l]]) return dst[d[pa][l]]; else return dst[d[pb-(1<<l)+1][l]]; } int dist(int a,int b) { if (a==0) a=Tree_rt; if (b==0) b=Tree_rt; return dst[a]+dst[b]-2*lca(a,b); } void dfs_add(int o,int fa) { s1[rt].Ins((dist(o,aim))); for (int i=h[o];i>=0;i=ne[i]) if (!ban[to[i]]&&to[i]!=fa) dfs_add(to[i],o); } void Divide(int o,int fat) { int root; dfs(o,-1); size=siz[o]; now=inf; dfs_rt(o,-1); root=rt; if (fat) fa[root]=fat; ban[root]=1; aim=fat; dfs_add(root,-1); s2[fat].Ins(s1[root].Top()); if (!col[root]) s2[root].Ins(0); for (int i=h[root];i>=0;i=ne[i]) if (!ban[to[i]]) Divide(to[i],root); if (s2[root].Size()>=2) { int tmp=s2[root].Top()+s2[root].S_Top(); lst.Ins(tmp); } } void dfs_dist(int o,int fat) { for (int i=h[o];i>=0;i=ne[i]) if (to[i]!=fat) dst[to[i]]=dst[o]+w[i],dfs_dist(to[i],o); } void Delete(int o) { if (s2[o].Size()>=2) lst.Del(s2[o].Top()+s2[o].S_Top()); s2[o].Del(0); if (s2[o].Size()>=2) { int tmp=s2[o].Top()+s2[o].S_Top(); lst.Ins(tmp); } if (s2[o].Size()>0) ans=max(ans,0); int now=o; while (now) { int fat=fa[now]; if (s2[fat].Size()>=2)lst.Del(s2[fat].Top()+s2[fat].S_Top()); int tmp=s1[now].Top(); s1[now].Del(dist(o,fat)); if (s1[now].Size()==0||tmp!=s1[now].Top()) { s2[fat].Del(tmp); if (s1[now].Size()>0) s2[fat].Ins(s1[now].Top()); } if (s2[fat].Size()>=2) { int tmp=s2[fat].Top()+s2[fat].S_Top(); lst.Ins(tmp); } if (s2[fat].Size()>0) ans=max(ans,0); now=fat; } } void Insert(int o) { if (s2[o].Size()>=2) { lst.Del(s2[o].Top()+s2[o].S_Top()); } s2[o].Ins(0); if (s2[o].Size()>=2) { int tmp=s2[o].Top()+s2[o].S_Top();lst.Ins(tmp); } if (s2[o].Size()>0) ans=max(ans,0); int now=o; while (now) { int fat=fa[now]; if (s2[fat].Size()>=2) lst.Del(s2[fat].Top()+s2[fat].S_Top()); int tmp,flag=0; if (s1[now].Size()==0) flag=1; else tmp=s1[now].Top(); s1[now].Ins(dist(o,fat)); if (flag||tmp!=s1[now].Top()) { if (!flag) s2[fat].Del(tmp); s2[fat].Ins(s1[now].Top()); } if (s2[fat].Size()>=2) { int tmp=s2[fat].Top()+s2[fat].S_Top(); lst.Ins(tmp); } if (s2[fat].Size()>0) ans=max(ans,0); now=fat; } } int Getint() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int main() { memset(h,-1,sizeof h); n=Getint(); F(i,1,n-1) { int a,b,c; a=Getint();b=Getint();c=Getint(); add(a,b,c);add(b,a,c); } tag=1; dfs(1,-1); now=inf; size=siz[1]; dfs_rt(1,-1); dfs_dist(rt,-1); tag=0; dfs(rt,-1); tag=1; F(i,2,cnt) _log[i]=_log[i>>1]+1; F(i,1,cnt) d[i][0]=b[i]; F(j,1,_log[cnt]) for (int i=1;i+(1<<j)-1<=cnt;++i) { if (dep[d[i][j-1]]<dep[d[i+(1<<j-1)][j-1]]) d[i][j]=d[i][j-1]; else d[i][j]=d[i+(1<<j-1)][j-1]; } Tree_rt=rt; Divide(1,0); scanf("%d",&m); F(i,1,m) { scanf("%s",opt); switch(opt[0]) { case 'A': if (lst.Size()) ans=max(ans,lst.Top());printf("%d\n",ans); break; case 'C': x=Getint();ans=-1; if (!col[x]) Delete(x); else Insert(x); col[x]^=1; break; } } }