我们考虑树剖,线段树上维护一个堆,保存不经过该段区间的路径的权值。
对于一条路径我们将对于线段树中的区间提取出来,在对于线段树中进行修改。也就是在堆中插入或删除。
对于一次询问,只要找到包含该点的线段中堆顶权值最大的就行了。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 10 typedef long long LL; 11 12 #define N 200010 13 14 struct data 15 { 16 int l,r; 17 }q[N]; 18 19 struct edge 20 { 21 int s,to,next; 22 }e[N<<1]; 23 int head[N<<1]; 24 int cnt; 25 26 int dep[N],siz[N],son[N],top[N],pos[N]; 27 int fa[N][20],val[N<<2]; 28 29 bool vis[N]; 30 31 int n,m; 32 int ans,res,num; 33 34 int askd; 35 36 struct cmp 37 { 38 bool operator() (int a,int b) 39 { 40 return val[a]<val[b]; 41 } 42 }; 43 44 priority_queue<int,vector<int>,cmp> Q[N<<2]; 45 46 bool cmp(data a,data b) 47 { 48 return a.l<b.l; 49 } 50 51 void link(int x,int y) 52 { 53 e[++cnt]=(edge){x,y,head[x]}; 54 head[x]=cnt; 55 } 56 57 void dfs(int x) 58 { 59 siz[x]=1; 60 son[x]=0; 61 for (int i=head[x];i;i=e[i].next) 62 { 63 int t=e[i].to; 64 if (t!=fa[x][0]) 65 { 66 dep[t]=dep[x]+1; 67 fa[t][0]=x; 68 dfs(t); 69 siz[x]+=siz[t]; 70 if (siz[t]>siz[son[x]]) 71 son[x]=t; 72 } 73 } 74 } 75 76 void dfs2(int x,int cha) 77 { 78 pos[x]=++res; 79 top[x]=cha; 80 if (son[x]) 81 dfs2(son[x],cha); 82 for (int i=head[x];i;i=e[i].next) 83 { 84 int t=e[i].to; 85 if (t!=fa[x][0] && t!=son[x]) 86 dfs2(t,t); 87 } 88 } 89 90 void build_lca() 91 { 92 for (int j=1;j<=18;j++) 93 for (int i=1;i<=n;i++) 94 if (fa[i][j-1]) 95 fa[i][j]=fa[fa[i][j-1]][j-1]; 96 } 97 98 int lca(int x,int y) 99 { 100 if (dep[x]<dep[y]) 101 swap(x,y); 102 int t=dep[x]-dep[y]; 103 for (int i=18;i>=0;i--) 104 if (t & (1<<i)) 105 x=fa[x][i]; 106 if (x==y) 107 return x; 108 for (int i=18;i>=0;i--) 109 if (fa[x][i]!=fa[y][i]) 110 x=fa[x][i],y=fa[y][i]; 111 return fa[x][0]; 112 } 113 114 void add(int nowl,int nowr,int now,int l,int r,int d) 115 { 116 if (l<=nowl && nowr<=r) 117 { 118 Q[now].push(d); 119 return ; 120 } 121 int mid=(nowl+nowr)>>1; 122 if (l<=mid) 123 add(nowl,mid,now<<1,l,r,d); 124 if (r>=mid+1) 125 add(mid+1,nowr,now<<1|1,l,r,d); 126 } 127 128 void query(int nowl,int nowr,int now,int d) 129 { 130 while (!Q[now].empty()) 131 { 132 int k=Q[now].top(); 133 if (vis[k]) 134 Q[now].pop(); 135 else 136 { 137 num=max(num,val[k]); 138 break; 139 } 140 } 141 if (nowl==nowr) 142 return ; 143 int mid=(nowl+nowr)>>1; 144 if (d<=mid) 145 query(nowl,mid,now<<1,d); 146 else 147 query(mid+1,nowr,now<<1|1,d); 148 } 149 int main() 150 { 151 scanf("%d%d",&n,&m); 152 int x,y; 153 for (int i=1;i<n;i++) 154 { 155 scanf("%d%d",&x,&y); 156 link(x,y); 157 link(y,x); 158 } 159 dep[1]=1; 160 dfs(1); 161 dfs2(1,1); 162 build_lca(); 163 for (int i=1;i<=m;i++) 164 { 165 scanf("%d",&askd); 166 if (askd==0) 167 { 168 scanf("%d%d%d",&x,&y,&val[i]); 169 int w=0,z=lca(x,y); 170 while (dep[top[x]]>dep[z]) 171 { 172 q[++w]=(data){pos[top[x]],pos[x]}; 173 x=fa[top[x]][0]; 174 } 175 while (dep[top[y]]>dep[z]) 176 { 177 q[++w]=(data){pos[top[y]],pos[y]}; 178 y=fa[top[y]][0]; 179 } 180 if (x!=z) 181 q[++w]=(data){pos[z],pos[x]}; 182 else if (y!=z) 183 q[++w]=(data){pos[z],pos[y]}; 184 else 185 q[++w]=(data){pos[z],pos[z]}; 186 q[++w]=(data){n+1,n+1}; 187 sort(q+1,q+w+1,cmp); 188 for (int j=1;j<=w;j++) 189 if (q[j-1].r<q[j].l-1) 190 add(1,n,1,q[j-1].r+1,q[j].l-1,i); 191 } 192 else if (askd==1) 193 { 194 scanf("%d",&x); 195 vis[x]=1; 196 } 197 else 198 { 199 scanf("%d",&x); 200 num=-1; 201 query(1,n,1,pos[x]); 202 printf("%d ",num); 203 } 204 } 205 return 0; 206 }