ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P6976 [NEERC2015]Distance on Triangulation

2022-07-09 18:36:43  阅读:202  来源: 互联网

标签:Distance Ns int luogu && NEERC2015 define D2 op


题面传送门
容易发现三角剖分一定是一个平面图。因此所有边除了在端点不交。
如果我们有一条边,并把这两个点及其相邻的边删去,则会分成两个联通块。如果一个询问的两端点分别在这两个联通块内,则这两个点之间的最短路一定会经过这条边两个端点中的一个。于是我们有了一个类似于分治的思想:每次选取一条边,跑出两个端点到当前联通块之间的答案,并处理当前在这个联通块内的询问。
如果我们每次选取的边都均分了这个联通块,则复杂度为\(O((n+q)\log n)\)可以接受。
问题在于选出这条边,我们一定是尽量想要选出分成的两部分最小值最大的边,这样子如果不是三角剖分实际上可以卡掉,但是三角剖分对偶后发现这个东西就是点分治的重心因此复杂度是正确的是\(O((n+q)\log n)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (100000+5)
#define M ((N<<2)+5)
#define K (350)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;vector<int> F[N];
int op[N],x,y,n,m,Sh,Ans[N],D1[N],D2[N];queue<int> Q;vector<int> Id;
struct Edge{int x,y;};vector<Edge>S;I bool cmp(Edge x,Edge y){return x.x^y.x?x.x<y.x:x.y<y.y;}struct Ques{int x,y,id;};vector<Ques> G;
namespace Tree{
	int F[N];I void Ins(int x,int y){while(x<=n) F[x]+=y,x+=x&-x;}I int Qry(int x){int Ans=0;while(x) Ans+=F[x],x-=x&-x;return Ans;}
}
I void Solve(vector<Edge> S,vector<Ques> G,vector<int> Id){
	if(G.empty()||S.empty()) return;int Ps=-1,x;Edge Ns;for(int i:Id) Tree::Ins(i,1);for(Edge i:S) x=Tree::Qry(i.y)-Tree::Qry(i.x-1),x=min(x,Id.size()-x),x>Ps&&(Ns=i,Ps=x);
	for(int i:Id) Tree::Ins(i,-1),F[i].clear();for(Edge i:S) F[i.x].PB(i.y),F[i.y].PB(i.x);//if(S.size()>1000)cerr<<S.size()<<' '<<G.size()<<' '<<Id.size()<<' '<<Ps<<'\n';
	for(int i:Id) D1[i]=D2[i]=1e9,op[i]=0;D1[Ns.x]=D2[Ns.y]=0;
	Q.push(Ns.x);while(!Q.empty()) {x=Q.front();Q.pop();for(int i:F[x]) D1[i]>D1[x]+1&&(Q.push(i),D1[i]=D1[x]+1);}
	Q.push(Ns.y);while(!Q.empty()) {x=Q.front();Q.pop();for(int i:F[x]) D2[i]>D2[x]+1&&(Q.push(i),D2[i]=D2[x]+1);}
	vector<int> I1,I2;vector<Edge> S1,S2;vector<Ques> G1,G2;I1.clear();I2.clear();S1.clear();S2.clear();G1.clear();G2.clear();
	for(Ques i:G) Ans[i.id]=min(min(min(D1[i.x]+D1[i.y],D2[i.x]+D2[i.y]),min(D1[i.x]+D2[i.y]+1,D1[i.y]+D2[i.x]+1)),Ans[i.id]);
	for(int i:Id) if(i>=Ns.x&&i<=Ns.y) op[i]=1,I1.PB(i);for(Ques i:G) op[i.x]==op[i.y]&&op[i.x]&&(G1.PB(i),0);for(Edge i:S) (i.x^Ns.x||i.y^Ns.y)&&op[i.x]==op[i.y]&&op[i.x]&&(S1.PB(i),0);
	for(int i:Id) if(i<=Ns.x||i>=Ns.y) op[i]=-1,I2.PB(i);for(Ques i:G) op[i.x]==op[i.y]&&op[i.x]==-1&&(G2.PB(i),0);for(Edge i:S) (i.x^Ns.x||i.y^Ns.y)&&op[i.x]==op[i.y]&&op[i.x]==-1&&(S2.PB(i),0);
	Solve(S1,G1,I1);Solve(S2,G2,I2);
} 
int main(){
	freopen("1.in","r",stdin);//freopen("karen.out","w",stdout);
	int i,j;scanf("%d",&n);for(i=1;i<=n;i++) S.PB((Edge){i,i%n+1});for(i=1;i<=n-3;i++) scanf("%d%d",&x,&y),S.PB((Edge){x,y});for(i=0;i<S.size();i++) S[i].x>S[i].y&&(swap(S[i].x,S[i].y),0);
	Me(Ans,0x3f);for(i=1;i<=n;i++) Id.PB(i);scanf("%d",&m);for(i=1;i<=m;i++) scanf("%d%d",&x,&y),x^y?(G.PB((Ques){x,y,i}),0):(Ans[i]=0);sort(S.begin(),S.end(),cmp);Solve(S,G,Id);for(i=1;i<=m;i++) printf("%d\n",Ans[i]); 
}

标签:Distance,Ns,int,luogu,&&,NEERC2015,define,D2,op
来源: https://www.cnblogs.com/275307894a/p/16461575.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有