P9058 [Ynoi2004] rpmtdq 與 P9678 [ICPC2022 Jinan R] Tree Distance

来源:https://www.cnblogs.com/rgw2010/p/18331112
-Advertisement-
Play Games

1、簡述C++中命名空間的作用。 答:避免重覆定義全局變數的問題。 2、定義兩個命名空間A 和 B 分別在A中和B中定義變數value。在main函數中將兩個空間的value列印出來。 #include "iostream" using namespace std; namespace A { in ...


思路:

註意到點對數量有 \(N^2\) 個,考慮丟掉一些無用的點對。

對於點對 \((x_1,y_1),(x_2,y_2)\),滿足 \(x_1 \le x_2 < y_2 \le y_1\),即區間 \([x_2,y_2]\)\([x_1,y_1]\) 包含,此時滿足若詢問到了 \([x_1,y_1]\),則一定會詢問到 \([x_2,y_2]\)

若滿足 \(\operatorname{dis}(x_1,y_1) \ge \operatorname{dis}(x_2,y_2)\),那麼此時可以將 \((x_1,y_1)\) 捨棄,因為若要用 \((x_1,y_1\)) 的貢獻,不如直接去看 \((x_2,y_2)\) 的貢獻,畢竟 \((x_1,y_1)\) 的貢獻一定不會比 \((x_2,y_2)\) 更優。

那麼我們可以定義若兩個點對 \((x_1,y_1),(x_2,y_2)\) 滿足以下條件,則稱 \((x_1,y_1)\)\((x_2,y_2)\) 支配

  • \(x_1 \le x_2 < y_2 \le y_1\)

  • \(\operatorname{dis}(x_1,y_1) \ge \operatorname{dis}(x_2,y_2)\)

此時定義一個支配點對滿足沒有被任何一個點對支配,即我們需要找出所有的支配點對來計算貢獻。

註意到是一個樹上點對距離問題,考慮點分治解決。

令當前分治重心\(rt\),對於點 \(v\),令 \(S_v\) 表示當前聯通塊中所有滿足 \(\operatorname{dis}(i,rt) \le \operatorname{dis}(v,rt)\)\(i\) 組成的一個集合

那麼可以與 \(v\) 組成支配點對的點一定是 \(S_v\)\(v\)前驅後繼,即 \(S_v\)\(<v\)最大的數\(>v\)最小的數

簡單證一下,設 \(S_v\)\(v\)前驅\(u\)

  • \(\operatorname{dis}(i,u) \le \operatorname{dis}(i,rt) + \operatorname{dis}(u,rt) \le \operatorname{dis}(i,rt) + \operatorname{dis}(v,rt) = \operatorname{dis}(i,v)\),即 \(\operatorname{dis}(i,u) \le \operatorname{dis}(i,v)\)

  • 註意到此時 \(i < u < v\)\(u < v < i\),即 \((i,v)\)\((i,u)\) 支配\((u,i)\)\((v,i)\) 支配

  • 那麼只有當 \(i=u\) 時,\((u,u)\) 點對不存在\((u,v)\) 不會被其它 \(S_v\) 中的點對支配。

後繼情況類似,就不多說了。

然後考慮如何快速找到支配點對,直接按照上面的方法找 \(S_v\),複雜度肯定是 \(O(N^2)\) 起步,考慮優化。

首先對於整個聯通塊的所有點,按照點的編號排序升序,然後維護一個 \(\operatorname{dis}(i,rt)\) 不降的單調棧

那麼有一個性質是,對於被點 \(i\) 彈出去的點 \(u\),肯定滿足 \(i\)\(u\) 後面第一個小於等於 \(\operatorname{dis}(u,rt)\) 的點且編號最小,即 \(i\)\(S_u\)\(u\)前驅;然後再倒著降序做一遍單調棧後繼即可。

此時我們來估算一下支配點對的數量,每個點最多被 \(\log N\)分治重心包含,每次包含最多增加 \(2\)支配點對,即總支配點對的數量為 \(N \log N\) 左右。

現在求出了全部的支配點對,即有貢獻的點對,現在考慮如何求被一個區間包含的所有支配點對的最小貢獻值,可以線上使用樹套樹,但是沒必要。

考慮離線使用掃描線演算法,因為樹狀數組不好維護尾碼最值,考慮倒著掃左端點,然後對於每個點對,在左端點處將右端點貢獻加入進去;那麼對於一個在左端點的詢問,就是一個首碼最小值。

時間複雜度為 \(O(N \log^2 N + Q \log N)\)

完整代碼:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const ll N=2e5+10,M=1e6+10,INF=1e18; 
bool Begin;
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');
}
int n,q;
ll ans[M];
vector<int> G[N];
vector<pair<int,ll>> E[N],Q[N];
void add(int u,int v,int w){
	E[u].push_back({v,w});
	E[v].push_back({u,w});
}
namespace Lowbit{
	ll a[N];
	inline void init(){
		for(int i=1;i<=n;i++)
		  a[i]=INF;
	}
	inline void add(int x,ll w){
		for(int i=x;i<=n;i+=lowbit(i))
		  a[i]=min(a[i],w);
	}
	inline ll query(int x){
		ll ans=INF;
		for(int i=x;i;i-=lowbit(i))
		  ans=min(ans,a[i]);
		return ans;
	}	
};
namespace LCA{
	int p[N],t[N],z[N],d[N],fa[N];
	ll dep[N];
	inline void dfs1(int u,int f){
		p[u]=1;
		for(auto t:E[u]){
			int v=t.first,w=t.second;
			if(v==f)
			  continue;
			dep[v]=dep[u]+w;
			d[v]=d[u]+1;
			fa[v]=u;
			dfs1(v,u);
			p[u]+=p[v];
			if(p[v]>p[z[u]])
			  z[u]=v;
		}
	}
	inline void dfs2(int u,int k){
		t[u]=k;
		if(!z[u])
		  return ;
		dfs2(z[u],k);
		for(auto t:E[u]){
			int v=t.first;
			if(v==fa[u]||v==z[u])
			  continue;
			dfs2(v,v);
		}
	}
	inline int Lca(int u,int v){
		while(t[u]!=t[v]){
			if(d[t[u]]<d[t[v]])
			  swap(u,v);
			u=fa[t[u]];
		}
		return d[u]<d[v]?u:v;
	}
	inline ll dis(int u,int v){
		return dep[u]+dep[v]-(dep[Lca(u,v)]<<1ll);
	}
	inline void init(){
		dfs1(1,1);
		dfs2(1,1);
	}
};
namespace Tree{
	int sum,cnt,top,Max,root;
	int T[N],siz[N];
	pair<int,ll> dis[N];
	bool del[N];
	inline void add(int x,int y){
		if(x>y)
		  swap(x,y);
		G[x].push_back(y);
	}
	inline void getroot(int u,int fa){
		int s=0;
		siz[u]=1;
		for(auto t:E[u]){
			ll v=t.first;
			if(del[v]||v==fa)
			  continue;
			getroot(v,u);
			siz[u]+=siz[v];
			s=max(s,siz[v]);
		}
		s=max(s,sum-siz[u]);
		if(s<Max){
			Max=s;
			root=u;
		}
	}
	inline void Get(int u,int p){
		root=0;
		sum=Max=p;
		getroot(u,0);
		getroot(root,0);
	}
	inline void getdis(int u,int fa,ll d){
		dis[++cnt]={u,d};
		for(auto t:E[u]){
			int v=t.first,w=t.second;
			if(v==fa||del[v])
			  continue;
			getdis(v,u,d+w);
		}
	}
	inline void calc(int u){
		cnt=0;
		getdis(u,0,0);
		sort(dis+1,dis+cnt+1);
		top=0;
		for(int i=1;i<=cnt;i++){
			while(top&&dis[i].second<=dis[T[top]].second){
				add(dis[i].first,dis[T[top]].first);
				top--;
			}
			T[++top]=i;
		}
		top=0;
		for(int i=cnt;i>=1;i--){
			while(top&&dis[i].second<=dis[T[top]].second){
				add(dis[i].first,dis[T[top]].first);
				top--;
			}
			T[++top]=i;			
		}
	}
	inline void solve(int u){
		calc(u);
		del[u]=1;
		for(auto t:E[u]){
			int v=t.first;
			if(del[v])
			  continue;
			Get(v,siz[v]);
			solve(root);
		}
	}	
	void work(){
		Lowbit::init();
		LCA::init();
		Get(1,n);
		solve(root);
	}
};
bool End;
int main(){
//	open("A.in","A.out");
	n=read();
	for(int u,v,w,i=1;i<n;i++){
		u=read(),v=read(),w=read();
		add(u,v,w); 
	}
	q=read();
	for(int l,r,i=1;i<=q;i++){
		l=read(),r=read();
		Q[l].push_back({i,r});
	}
	Tree::work();
	for(int i=n;i>=1;i--){
		for(auto v:G[i])
		  Lowbit::add(v,LCA::dis(i,v));
		for(auto t:Q[i])
		  ans[t.first]=Lowbit::query(t.second);
	}
	for(int i=1;i<=q;i++){
		write(ans[i]==INF?-1:ans[i]);
		putchar('\n');
	}
	cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
	return 0;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文由leetcode的字元異位詞分組題目引入,記錄了javascript中對象的鍵的數據類型以及存在的數據類型轉換現象。 ...
  • 摘要:本文介紹Nuxt 3中useRequestEventHook的使用,可訪問請求路徑、方法和頭部信息,適用於SSR環境下處理請求邏輯,如中間件、插件及API路由。僅伺服器端生效,需註意安全性。 ...
  • 引言 在JavaScript開發中,設計模式是解決特定問題的有效手段。單例模式(Singleton Pattern)是其中一種常見且有用的模式。儘管網上有許多關於單例模式的解釋和實現,本篇將從實際工作中的需求出發,探討如何更好地理解和應用單例模式,以編寫更復用、更高效的代碼。 什麼是單例模式? 單例 ...
  • 手寫 Hibernate 系列 手寫 Hibernate ORM 框架 00-hibernate 簡介 手寫 Hibernate ORM 框架 00-環境準備 手寫 Hibernate ORM 框架 01-註解常量定義 手寫 Hibernate ORM 框架 02-實體 Bean 定義,建表語句自動 ...
  • 本文主要介紹了在使用Python進行面向對象編程時,異常的層級和如何使用繼承關係完成自定義自己項目中異常類,並以感測器數據採集為例進行講解。 ...
  • 拓展閱讀 Java Servlet 教程-20-自己手寫實現 spring mvc 整體思路 Java Servlet 教程-21-自己手寫 spring mvc 簡單實現 Spring Web MVC-00-重學 mvc mvc-01-Model-View-Controller 概覽 mvc-02 ...
  • 題目要求 給定兩個字元串 s 和 t ,編寫一個函數來判斷 t 是否是 s 的字母異位詞。 註意:若 s 和 t 中每個字元出現的次數都相同,則稱 s 和 t 互為字母異位詞。 由於字元在電腦記憶體中是以ASCII碼或Unicode編碼的形式存儲的,我們可以得出'a'在ASCII表中的值是97,'A ...
  • PART1: Java基礎知識概述與Java的下載安裝 1)Java語言概述: ① Java的發展史: 詹姆斯·高斯林(James Gosling) 1977年獲得了加拿大卡爾加里大學電腦科學學士學位,1983年獲得了美國卡內基梅隆大學電腦科學博士學位,畢業後到IBM工作,設計IBM第一代工作站 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...