给一棵带权树,三种操作,查询x到y的的路径上最大的边权;修改第x条边的权值为y;取反x到y的路径上所有的边权。每次查询,求出lca,从x,y爬到lca点取最大值,修改直接改权值就行,取反同查询...一定是这题的数据太弱了...这么暴力的做法都给过......
#include <iostream> #include <cstdio> #include <cmath> #include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int POW = 18; const int maxn=201000; struct node { int v,w,id; node() { } node(int x,int y,int z) { v=x; w=y; id=z; } }; vector<node> edge[maxn]; int w[maxn]; int p[maxn][22]; int d[maxn]; int f[maxn]; int n,m,k; node pre[maxn]; void dfs(int u,int fa){ d[u]=d[fa]+1; p[u][0]=fa; for(int i=1;i<POW;i++) p[u][i]=p[p[u][i-1]][i-1]; int sz=edge[u].size(); for(int i=0;i<sz;i++){ int v=edge[u][i].v; if(v==fa) continue; dfs(v,u); pre[v]=edge[u][i]; f[v]=u; } } int lca( int a, int b ){ if( d[a] > d[b] ) swap(a,b); if( d[a] < d[b] ){ int del = d[b] - d[a]; for( int i = 0; i < POW; i++ ) if(del&(1<<i)) b=p[b][i]; } if( a != b ){ for( int i = POW-1; i >= 0; i-- ) if( p[a][i] != p[b][i] ) a = p[a][i] , b = p[b][i]; a = p[a][0], b = p[b][0]; } return a; } char cmd[10]; int main() { // freopen("in.txt","r",stdin); int tt; scanf("%d",&tt); while(tt--) { memset(d,0,sizeof d); memset(p,0,sizeof p); memset(pre,0,sizeof pre); memset(f,0,sizeof f); memset(w,0,sizeof w); scanf("%d",&n); int x,y,z; for (int i=1; i<=n; i++) { edge[i].clear(); } for (int i=1; i<n; i++) { scanf("%d%d%d",&x,&y,&z); edge[x].push_back(node(y,z,i)); edge[y].push_back(node(x,z,i)); w[i]=z; } dfs(1,-1); while(true) { scanf("%s",cmd); if (cmd[0]=='Q') { scanf("%d%d",&x,&y); int t=lca(x,y); int minn=(1<<30); minn=-minn; while (x!=t) { minn=max(minn,w[pre[x].id]); x=f[x]; } while (y!=t) { minn=max(minn,w[pre[y].id]); y=f[y]; } printf("%d\n",minn); } else if (cmd[0]=='C') { scanf("%d%d",&x,&y); w[x]=y; } else if (cmd[0]=='N') { scanf("%d%d",&x,&y); int t=lca(x,y); while (x!=t) { w[pre[x].id]=-w[pre[x].id]; x=f[x]; } while (y!=t) { w[pre[y].id]=-w[pre[y].id]; y=f[y]; } } else break; } } return 0; }