参考论文: 郭华阳《RMQ与LCA问题》 的解法.
通过构建最小生成树,然后转换成 寻找最近公共祖先来求解, 逆序处理询问,将删除改成添加边.
代码在BZOJ上WA了.暂时未找到原因, 先放着... 不过有看到用splay, 动态树等做的..
#include<cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <map> #include <vector> using namespace std; const int N = ( int )1e5+ 10 ; const int M = ( int )1e6+ 10 ; const int maxn = 5 * N; int n, m, Q_num; struct node{ int a, b, t; bool operator < ( const node &tmp) const { return t < tmp.t; } }edge[M]; struct Query{ int k,a,b; }Q[N]; map < pair< int , int >, int > mp; vector < int > S[ 2 *N+ 10 ]; int getint(){ char ch = getchar(); for (; ch > ' 9 ' || ch < ' 0 ' ; ch = getchar() ); int tmp = 0 ; for (; ch > ' 0 ' && ch < ' 9 ' ; ch = getchar() ) tmp = tmp* 10 + ch - ' 0 ' ; return tmp; } int st[maxn], top; bool vis[M]; int find( int x){ return st[x] == x ? x : find(st[x]); } void debug(){ printf( " n = %d, m = %d, Q_num = %d\n " , n, m, Q_num ); printf( " Edge:\n " ); for ( int i = 0 ; i < m; i++ ) printf( " (%d,%d,t=%d)\n " , edge[i].a, edge[i].b, edge[i].t ); printf( " Query:\n " ); for ( int i = 0 ; i < Q_num; i++ ) printf( " k=%d,(%d,%d)\n " , Q[i].k, Q[i].a, Q[i].b ); } void input(){ n = getint(); m = getint(); Q_num = getint(); for ( int i = 0 ; i < m; i++){ // Edge infomation edge[i].a = getint(); edge[i].b = getint(); edge[i].t = getint(); } for ( int i = 0 ; i < Q_num; i++){ // Query Q[i].k = getint(); Q[i].a = getint(); Q[i].b = getint(); } sort( edge, edge +m ); // sort by t desc for ( int i = 0 ; i < m; i++) // index mp[ make_pair( edge[i].a, edge[i].b ) ] = mp[ make_pair( edge[i].b, edge[i].a ) ] = i; for ( int i = 0 ; i < Q_num; i++ ){ if ( Q[i].k == 2 ) vis[ mp[make_pair(Q[i].a, Q[i].b)] ] = true ; } // for(int i = 0; i < m; i++) // printf("%d ", vis[i] ); puts(""); } int val[maxn]; int pos[maxn], dep[maxn], vec[maxn], idx; int dp[maxn][ 50 ]; void dfs( int u, int d){ dep[ ++idx] = d; vec[idx] = u; if ( pos[u] == - 1 ) pos[u] = idx; dep[idx] = d; for ( int i = 0 ; i < ( int )S[u].size(); i++ ){ dfs( S[u][i], d + 1 ); dep[ ++idx] = d; vec[idx] = u; } } void print(){ printf( " Top = %d\n " , top); for ( int i = 1 ; i <= top; i++) printf( " pos[%d] = %d, val[%d] = %d\n " , i, pos[i], i, val[i]); printf( " idx = %d\n " , idx); for ( int i = 1 ; i <= idx; i++ ) printf( " i = %d, vec[%d] = %d, dep[%d] = %d\n " , i, i, vec[i], i, dep[i] ); } void predeal(){ for ( int i = 0 ; i < 2 *n+ 10 ; i++ ) st[i] = i, S[i].clear(); top = n; for ( int i = 0 ; i < m; i++ ){ if ( vis[ mp[ make_pair( edge[i].a, edge[i].b ) ] ] == false ){ int a = edge[i].a, b = edge[i].b, t = edge[i].t; int x = find(a), y = find(b); // printf("(%d,%d): x = %d, y = %d\n",a,b, x, y ); if ( x != y ){ st[x] = st[y] = ++ top; val[top] = t; S[top].push_back(x), S[top].push_back(y); } } } for ( int i = 1 ; i <= top; i++ ) pos[i] = - 1 ; idx = 0 ; dfs( top, 0 ); // print(); // init RMQ for ( int i = 1 ; i <= idx; i++ ) dp[i][ 0 ] = i; for ( int j = 1 ; ( 1 <<j) <= idx; j++ ){ for ( int i = 1 ; i+( 1 <<j)- 1 <= idx; i++ ){ // dp[i][j] = min( dp[i][j-1], dp[i+(1<<(j-1))][j-1] ); if ( dep[ dp[i][j- 1 ] ] < dep[ dp[i+( 1 <<(j- 1 ))][j- 1 ] ] ) dp[i][j] = dp[i][j- 1 ]; else dp[i][j] = dp[i+( 1 <<(j- 1 ))][j- 1 ]; } } } int RMQ_find( int l, int r){ int d = r-l+ 1 , k = 0 ; while ( ( 1 <<(k+ 1 )) < d ) k++ ; // printf("RMQ: k = %d\n", k ); // printf("RMQ: L = %d, R = %d\n", dp[l][k] , dp[r-(1<<k)+1][k] ); if ( dep[ dp[l][k] ] < dep[ dp[r-( 1 <<k)+ 1 ][k] ] ) return dp[l][k]; return dp[ r-( 1 <<k)+ 1 ][k]; } int ans[M], ans_cnt; void solve(){ int ans_cnt = 0 ; predeal(); for ( int i = Q_num- 1 ; i >= 0 ; i-- ){ if ( Q[i].k == 1 ){ int l = pos[ Q[i].a ], r = pos[ Q[i].b ]; // printf("(a=%d,b=%d),(l=%d,r=%d)\n", Q[i].a, Q[i].b, l, r); if ( l > r ) swap( l, r ); int pt = RMQ_find(l,r); // printf("pt = %d\n", pt ); ans[ ans_cnt++ ] = val[ vec[pt] ]; } else { // Q[i].k == 2 vis[ mp[ make_pair( Q[i].a,Q[i].b ) ] ] = false ; predeal(); // restructrue the min genaration tree } // puts("******************************************************"); } for ( int i = ans_cnt- 1 ; i >= 0 ; i-- ){ printf( " %d\n " , ans[i] ); } } int main(){ freopen( " 1.in " , " r " ,stdin); input(); solve(); return 0 ; }