SPOJ QTREE Query on a tree V
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. We define dist(a, b) as the number of edges on the path from node a to node b.
Each node has a color, white or black. All the nodes are black initially.
We will ask you to perfrom some instructions of the following form:
- 0 i : change the color of i-th node(from black to white, or from white to black).
- 1 v : ask for the minimum dist(u, v), node u must be white(u can be equal tov). Obviously, as long as node v is white, the result will always be 0.
Input
- In the first line there is an integer N (N <= 100000)
- In the next N-1 lines, the i-th line describes the i-th edge: a line with two integers a b denotes an edge between a and b.
- In the next line, there is an integer Q denotes the number of instructions (Q <= 100000)
- In the next Q lines, each line contains an instruction "0 i" or "1 v"
Output
For each "1 v" operation, print one integer representing its result. If there is no white node in the tree, you should write "-1".
Example
Input: 10 1 2 1 3 2 4 1 5 1 6 4 7 7 8 5 9 1 10 10 0 6 0 6 0 6 1 3 0 1 0 1 1 3 1 10 1 4 1 6 Output: 2 2 2 3 0
改变某点颜色,或者询问离某点最近的白点离询问点的距离
LCT
在LCT上,把未激活的树枝全丢到set里。
花式更新状态,记录链左端点的最近白点距离,右端点的最近白点距离。注意更新左边来(深度更浅处)的答案时,要加上下放到当前点的边权。
统计答案时,access(x),使得x在当前链的最右端,Splay(x)将x提为根,那么结点上记录的“离右端点最近的白点距离”就是答案了。
说着简单,调了三四个小时,也是绝望(然而只是绝望的开始)
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<set> 8 using namespace std; 9 const int INF=1e7; 10 const int mxn=100010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int fir(multiset<int> &s){return s.size()? *s.begin():INF;} 18 struct edge{ 19 int v,nxt; 20 }e[mxn<<1]; 21 int hd[mxn],mct=0; 22 void add_edge(int u,int v){ 23 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 24 } 25 // 26 struct node{int ch[2],fa;}t[mxn]; 27 multiset<int>pt[mxn]; 28 int len[mxn],L[mxn],R[mxn],sum[mxn],mians[mxn]; 29 int w[mxn],col[mxn]; 30 void init(int n){ 31 for(int i=0;i<=n;i++)w[i]=INF,col[i]=1; 32 for(int i=0;i<=n;i++){L[i]=R[i]=mians[i]=INF;} 33 return; 34 } 35 inline bool isroot(int x){return (t[t[x].fa].ch[0]!=x && t[t[x].fa].ch[1]!=x);} 36 void pushup(int x){ 37 if(!x)return; 38 int lc=t[x].ch[0],rc=t[x].ch[1]; 39 sum[x]=len[x]+sum[lc]+sum[rc]; 40 int m0=min(w[x],fir(pt[x])); 41 // printf("m0:%d\n",m0); 42 int ml=min(R[lc]+len[x],m0); 43 int mr=min(L[rc],m0); 44 L[x]=min(L[lc],sum[lc]+len[x]+mr); 45 R[x]=min(R[rc],sum[rc]+ml); 46 return; 47 } 48 void rotate(int x){ 49 int y=t[x].fa,z=t[y].fa,lc,rc; 50 if(t[y].ch[0]==x)lc=0;else lc=1;rc=lc^1; 51 if(!isroot(y)){t[z].ch[t[z].ch[1]==y]=x;} 52 t[x].fa=z;t[y].fa=x; 53 t[t[x].ch[rc]].fa=y;t[y].ch[lc]=t[x].ch[rc]; 54 t[x].ch[rc]=y; 55 pushup(y); 56 return; 57 } 58 void Splay(int x){ 59 while(!isroot(x)){ 60 int y=t[x].fa,z=t[y].fa; 61 if(!isroot(y)){ 62 if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x); 63 else rotate(y); 64 } 65 rotate(x); 66 } 67 pushup(x); 68 return; 69 } 70 void access(int x){ 71 for(int y=0;x;x=t[x].fa){ 72 Splay(x); 73 if(t[x].ch[1]){pt[x].insert(L[t[x].ch[1]]);} 74 if(y) pt[x].erase(pt[x].find(L[y])); 75 t[x].ch[1]=y; 76 pushup(x); 77 y=x; 78 } 79 return; 80 } 81 void change(int x){ 82 access(x);Splay(x); 83 // printf("col:%d\n",col[x]); 84 col[x]^=1; 85 // printf("col:%d\n",col[x]); 86 if(!col[x])w[x]=0;else w[x]=INF; 87 // printf("!!!change:%d to %d\n",x,w[x]); 88 pushup(x); 89 return; 90 } 91 int query(int x){ 92 access(x); 93 Splay(x); 94 pushup(x); 95 return R[x]; 96 } 97 //LCT 98 void DFS(int u,int fa){ 99 for(int i=hd[u];i;i=e[i].nxt){ 100 if(e[i].v==fa)continue;int v=e[i].v; 101 t[v].fa=u; 102 len[v]=1; 103 DFS(v,u); 104 // pt[u].insert(mians[v]); 105 pt[u].insert(L[v]); 106 } 107 pushup(u); 108 return; 109 } 110 int n,Q; 111 int main(){ 112 int i,j,u,v; 113 n=read(); 114 for(i=1;i<n;i++){ 115 u=read();v=read(); 116 add_edge(u,v); 117 add_edge(v,u); 118 } 119 init(n); 120 DFS(1,0); 121 Q=read(); 122 while(Q--){ 123 u=read();v=read(); 124 if(u){ 125 int ans=query(v); 126 if(ans>=INF)printf("-1\n"); 127 else printf("%d\n",ans); 128 } 129 else{change(v);} 130 } 131 return 0; 132 }
本文为博主原创文章,转载请注明出处。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!