1. 程式人生 > 實用技巧 >tomcat8.5.57原始碼閱讀筆記5.1 - 管道

tomcat8.5.57原始碼閱讀筆記5.1 - 管道

前言

第一道用線段樹優化建邊做的題,還是比較有記錄意義的

當然也有對Rick姥爺的膜拜 orz

話說Rick為啥會給Morty留遺產

題目

洛谷

CF

講解

首先操作一有手就行

問題是點連區間和區間連點的操作不好搞

區間?你會想到什麼?

線段樹!

直接讓線段樹上的點連邊,表示點連區間和區間連點

但是我們發現一個問題,大區間可以由小區間組成,這會引起什麼?

大區間可以走向單點,組成它的小區間也可以走向單點

單點可以走向小區間,單點也可以走向大區間

細品這兩句話↑

所以我們需要兩棵線段樹分別維護走出去(從線段樹走出去到單點,後者同理)和走進來

一切都變得簡單了,注意long long和陣列大小

我才不會用vector去卡空間,哼

程式碼

int head[MAXN * 9],tot;
struct edge
{
	int v,w,nxt;
}e[MAXN * 40];
void Add_Edge(int x,int y,int z)
{
	e[++tot].v = y;
	e[tot].w = z;
	e[tot].nxt = head[x];
	head[x] = tot;
}

int lc[MAXN * 9],rc[MAXN * 9],cnt;
int Build(int l,int r,int t)
{
	if(l == r) return l;
	int mid = (l+r) >> 1;
	int x = ++cnt;
	lc[x] = Build(l,mid,t);
	rc[x] = Build(mid+1,r,t);
	if(t == 1) Add_Edge(x,lc[x],0),Add_Edge(x,rc[x],0);//點連區間,往下走 
	else Add_Edge(lc[x],x,0),Add_Edge(rc[x],x,0);//區間連點,往上走 
	return x;
}
void update(int x,int l,int r,int ql,int qr,int ID,int val,int t)
{
	if(ql <= l && r <= qr)
	{
		if(t == 1) Add_Edge(ID,x,val);
		else Add_Edge(x,ID,val);
		return;
	}
	int mid = (l+r) >> 1;
	if(ql <= mid) update(lc[x],l,mid,ql,qr,ID,val,t);
	if(mid+1 <= qr) update(rc[x],mid+1,r,ql,qr,ID,val,t);
}

LL dis[MAXN * 9];
struct node
{
	int u;LL val;
	node(){}
	node(int u1,LL val1){
		u = u1;
		val = val1;
	}
	bool operator < (const node &px)const{
		return val > px.val;
	}
};
void dijkstra()
{
	for(int i = 1;i <= cnt;++ i) dis[i] = INF;
	priority_queue<node> q;
	q.push(node(S,dis[S] = 0));
	while(!q.empty())
	{
		node t = q.top(); q.pop();
		if(t.val > dis[t.u]) continue;
		for(int i = head[t.u]; i ;i = e[i].nxt)
			if(dis[e[i].v] > dis[t.u] + e[i].w)
				q.push(node(e[i].v,dis[e[i].v] = dis[t.u] + e[i].w));
	}
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read(); m = Read(); S = Read();
	cnt = n;
	rt1 = Build(1,n,1); rt2 = Build(1,n,2);
	while(m--)
	{
		int opt = Read(),u = Read(),l = Read(),r = Read();
		if(opt == 1) Add_Edge(u,l,r);
		else if(opt == 2) update(rt1,1,n,l,r,u,Read(),1);
		else update(rt2,1,n,l,r,u,Read(),2);
	}
	dijkstra();
	for(int i = 1;i <= n;++ i) Put(dis[i] == INF ? -1 : dis[i],' ');
	return 0;
}