<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      P6071 『MdOI R1』Treequery

      P6071 『MdOI R1』Treequery

      簡單分討題。

      \([l, r]\) 內的點全部在 \(p\) 子樹內:

      • 考慮找到 \(q = \operatorname{LCA}(l, l + 1, \cdots, r - 1, r)\),顯然 \(q\) 也在 \(p\) 子樹內,那么答案為 \(\operatorname{dis}(p, q) = dep_q - dep_p\)

      \([l, r]\) 內的點一部分在 \(p\) 子樹內,一部分在外面:

      • 顯然,此時答案為 \(0\)

      否則若 \([l, r]\) 內的點全部都在 \(p\) 子樹外:

      • 顯然我們先應該找到 \(q \in [l, r], \operatorname{LCA}(p, q)\) 中深度最深的那個點 \(q\)

      • 轉化一下,即我們只用找到一個點 \(q\),滿足 \(q\)\(p\) 祖先且 \(q\) 子樹內包含 \([l, r]\) 中其中一個點即可且是滿足這些條件中最深的,可以倍增暴力跳然后判斷。

      • 然后需要繼續特判:若 \(q\) 子樹內包含了所有的 \([l, r]\),那么令 \(R = \operatorname{LCA}(l, l + 1, \cdots, r - 1, r)\),故 \(R\) 肯定在 \(q\) 子樹內,答案為 \(\operatorname{dis}(p, R) = dep_p + dep_R - 2dep_q\)。否則只有一部分在 \(p\) 子樹內,其它的在外面,則答案為 \(\operatorname{dis}(p, q) = dep_p - dep_q\)

      然后說一下如何判斷 \(p\) 子樹內有多少個點在 \([l, r]\) 范圍內,考慮差分為 \([1, r] - [1, l - 1]\),然后只需要考慮前綴;考慮使用主席樹,即 \(T_i\) 維護了編號為 \([1, i]\) 的點的時間戳序列,\(T_i \to T_{i + 1}\) 只需要單點修改 \(dfn_{i + 1}\) 即可;查詢則在 \(T_r\)\(T_{l - 1}\) 查詢區間 \([dfn_p, dfn_p + siz_p - 1]\) 和即可。

      哦,還有個查詢區間 \(\operatorname{LCA}\),可以轉化為相鄰 \(\operatorname{LCA}\) 中深度最小的那個,那么使用 ST 表即可做到單 \(\log\)

      套上倍增,時間復雜度為 \(O(N \log^2 N)\),空間復雜度為 \(O(N \log N)\)

      link

      完整代碼:

      #include<bits/stdc++.h>
      #define lowbit(x) x & (-x)
      #define pi pair<ll, ll>
      #define ls(k) k << 1
      #define rs(k) k << 1 | 1
      #define fi first
      #define se second
      using namespace std;
      typedef __int128 __;
      typedef long double lb;
      typedef double db;
      typedef unsigned long long ull;
      typedef long long ll;
      const int N = 2e5 + 10, M = 20;
      inline ll read(){
          ll x = 0, f = 1;
          char c = getchar();
          while(c < '0' || c > '9'){
              if(c == '-')
                f = -1;
              c = getchar();
          }
          while(c >= '0' && c <= '9'){
              x = (x << 1) + (x << 3) + (c ^ 48);
              c = getchar();
          }
          return x * f;
      }
      inline void write(ll x){
      	if(x < 0){
      		putchar('-');
      		x = -x;
      	}
      	if(x > 9)
      	  write(x / 10);
      	putchar(x % 10 + '0');
      }
      ll d[N];
      int n, q, u, v, w, p, l, r, ans, cnt;
      int dfn[N], siz[N], dep[N], top[N], son[N], lg[N], fa[N], rt[N], Fa[M][N];
      pair<int, int> F[M][N];
      vector<pair<int, int>> E[N];
      inline void add(int u, int v, int w){
      	E[u].push_back({v, w});
      	E[v].push_back({u, w});
      }
      namespace Seg{
      	int node;
      	struct Node{
      		int lson, rson;
      		int sum;
      	}X[N * 40];
      	inline void newnode(int &k){
      		X[++node] = X[k];
      		k = node;
      	}
      	inline void update(int &k, int l, int r, int i){
      		newnode(k);
      		++X[k].sum;
      		if(l == i && i == r)
      		  return ;
      		int mid = (l + r) >> 1;
      		if(i <= mid)
      		  update(X[k].lson, l, mid, i);
      		else
      		  update(X[k].rson, mid + 1, r, i);
      	}
      	inline int ask(int k, int l, int r, int ql, int qr){
      		if(!k)
      		  return 0;
      		if(l == ql && qr == r)
      		  return X[k].sum;
      		int mid = (l + r) >> 1;
      		if(qr <= mid)
      		  return ask(X[k].lson, l, mid, ql, qr);
      		else if(ql > mid)
      		  return ask(X[k].rson, mid + 1, r, ql, qr);
      		else
      		  return ask(X[k].lson, l, mid, ql, mid) + ask(X[k].rson, mid + 1, r, mid + 1, qr);
      	}
      };
      inline void dfs1(int u, int f){
      	for(int i = 1; i < M; ++i)
      	  Fa[i][u] = Fa[i - 1][Fa[i - 1][u]];
      	siz[u] = 1;
      	for(auto t : E[u]){
      		int v = t.fi, w = t.se;
      		if(v == f)
      		  continue;
      		d[v] = d[u] + w;
      		dep[v] = dep[u] + 1;
      		fa[v] = Fa[0][v] = u;
      		dfs1(v, u);
      		siz[u] += siz[v];
      		if(siz[v] > siz[son[u]])
      		  son[u] = v;
      	}
      }
      inline void dfs2(int u, int k){
      	dfn[u] = ++cnt;
      	top[u] = k;
      	if(!son[u])
      	  return ;
      	dfs2(son[u], k);
      	for(auto t : E[u]){
      		int v = t.fi;
      		if(v == fa[u] || v == son[u])
      		  continue;
      		dfs2(v, v);
      	}
      }
      inline int lca(int u, int v){
      	while(top[u] != top[v]){
      		if(dep[top[u]] < dep[top[v]])
      		  swap(u, v);
      		u = fa[top[u]];
      	}
      	return dep[u] < dep[v] ? u : v;
      }
      inline int LCA(int l, int r){
      	if(l == r)
      	  return l;
      	--r;
      	int k = lg[r - l + 1];
      	return min(F[k][l], F[k][r - (1 << k) + 1]).se;
      }
      inline int ASK(int u, int l, int r){
      	return Seg::ask(rt[r], 1, n, dfn[u], dfn[u] + siz[u] - 1) - Seg::ask(rt[l - 1], 1, n, dfn[u], dfn[u] + siz[u] - 1);
      }
      int main(){
      //	freopen("A.in", "r", stdin);
      //	freopen("A.out", "w", stdout);
      	lg[0] = -1;
      	n = read(), q = read();
      	for(int i = 1; i < n; ++i){
      		lg[i] = lg[i >> 1] + 1;
      		u = read(), v = read(), w = read();
      		add(u, v, w);
      	}
      	dfs1(1, 1);
      	dfs2(1, 1);
      	for(int i = 1; i <= n; ++i){
      		rt[i] = rt[i - 1];
      		Seg::update(rt[i], 1, n, dfn[i]);
      	}
      	for(int i = 1; i < n; ++i){
      		u = lca(i, i + 1);
      		F[0][i] = {dep[u], u};
      	}
      	for(int j = 1; j < M; ++j)
      	  for(int i = 1; i + (1 << j) <= n; ++i)
      	    F[j][i] = min(F[j - 1][i], F[j - 1][i + (1 << (j - 1))]);
      	while(q--){
      		p = read() ^ ans, l = read() ^ ans, r = read() ^ ans;
      		int now = ASK(p, l, r), all = LCA(l, r);
      		if(now == r - l + 1)
      		  ans = d[all] - d[p];
      		else if(!now){
      			int q = p;
      			for(int i = M - 1; i >= 0; --i)
      			  if(Fa[i][q] && !ASK(Fa[i][q], l, r))
      			    q = Fa[i][q];
      			q = fa[q];
      			now = ASK(q, l, r);
      			if(now == r - l + 1)
      			  ans = d[all] + d[p] - (d[q] << 1ll);
      			else
      			  ans = d[p] - d[q];
      		}
      		else
      		  ans = 0;
      		write(ans);
      		putchar('\n');
      	}
      	return 0;
      }
      
      posted @ 2025-06-11 15:54  rgw2010  閱讀(45)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品一区国产| 亚洲天堂在线观看完整版| 国产精品一区二区三区四区| 欧美黑人粗暴多交高潮水最多| 色综合天天综合网天天看片| 天天燥日日燥| 亚洲综合无码明星蕉在线视频| 福利视频一区二区在线| 日韩中文字幕一区二区不卡| 国产91特黄特色A级毛片| 亚洲精品二区在线播放| 免费超爽大片黄| 夜夜爽免费888视频| 国产办公室秘书无码精品99| 久久99久国产精品66| 与子乱对白在线播放单亲国产| 国产精品中文字幕久久| 中文字幕av无码免费一区| 中文字幕在线精品人妻| 国产综合一区二区三区麻豆| 国产日产亚洲系列最新| 精品无码久久久久久久久久| 午夜福利理论片高清在线| 亚洲av片在线免费观看| 久久久久综合中文字幕| 国产一区二区不卡在线| 毛多水多高潮高清视频| 欧美大片va欧美在线播放| 少妇xxxxx性开放| 国产精品一区二区三区日韩| 亚洲www永久成人网站| 久久人人97超碰人人澡爱香蕉| 日本欧美一区二区三区在线播放| 欧洲无码一区二区三区在线观看| 少妇精品无码一区二区免费视频| 国产不卡一区二区四区| a片免费视频在线观看| 一 级做人爱全视频在线看| 国产农村老熟女国产老熟女| 国产成人亚洲综合图区| 乱码精品一区二区三区|