1. 程式人生 > 實用技巧 >Vue常用特性-計算屬性computed 和 偵聽器 watch

Vue常用特性-計算屬性computed 和 偵聽器 watch

前言

T4正解李超線段樹?不會,滾過來學

保留節目百度百科自學已被刪除

講解

貌似思路並不是很難的亞子

我們需要線上支援一下兩個操作:

  • 插入一條線段

  • 給定\(x_0\),詢問當\(x=x_0\)時所有線段的最高點

我們可以使用權值線段樹!

對於每個區間,我們維護一個最優線段

1.插入

顯然對於一個線段完全覆蓋的區間我們才處理

分四種情況討論:

(1).當前區間無最優線段

直接賦值

(2).當前線段完全覆蓋最優線段

直接賦值

(3).當前線段完全被最優線段覆蓋

直接滾粗

(4).相交

最複雜的情況,我們考慮將覆蓋該區間最長的線段保留為最優線段

欸嘿?怎麼搞呢?其實只需判斷該區間中點誰在上面就行了,中點位置在上面的線段一定是覆蓋最長的線段

然後把另外一條丟到下面去接著修改

插入時間複雜度\(O(\log^2 n)\)

2.詢問

一直往下走,對於每個走到的區間的最優線段求出一個函式值,取\(\texttt{max}\)即可

詢問時間複雜度\(O(\log n)\)

練習

loj板題「雅禮集訓 2017 Day2」線段遊戲

程式碼

「雅禮集訓 2017 Day2」線段遊戲

const int M = 1000001;
const int MAXN = 2000005;
int n,Q;
struct line
{
	double k,b;
	bool f;
	line(){}
	line(double k1,double b1,bool f1){
		k = k1;
		b = b1;
		f = f1;
	}
};
#define lc (x<<1)
#define rc (x<<1|1)
double getf(line w,int x){return w.k * x + w.b;}
struct LiChaoSegmentTree
{
	line t[MAXN << 2];
	void Add(int x,int l,int r,int ql,int qr,line w)
	{
		int mid = (l+r) >> 1; 
		if(ql <= l && r <= qr)
		{
			if(!t[x].f) t[x] = w;
			else if(getf(w,l) >= getf(t[x],l) && getf(w,r) >= getf(t[x],r)) t[x] = w;
			else if(getf(w,l) <= getf(t[x],l) && getf(w,r) <= getf(t[x],r)) return;
			else
			{
				if(getf(w,mid) >= getf(t[x],mid)) swap(w,t[x]);
				if(getf(w,l) > getf(t[x],l)) Add(lc,l,mid,ql,qr,w);
				else Add(rc,mid+1,r,ql,qr,w);
			}
			return;
		}
		if(ql <= mid) Add(lc,l,mid,ql,qr,w);
		if(mid+1 <= qr) Add(rc,mid+1,r,ql,qr,w);
	}
	
	double Query(int x,int l,int r,int q)
	{
		double ret = -M;
		if(l <= q && q <= r && t[x].f) ret = getf(t[x],q);
		if(l == r) return ret;
		int mid = (l+r) >> 1; 
		if(q <= mid) ret = Max(ret,Query(lc,l,mid,q));
		else ret = Max(ret,Query(rc,mid+1,r,q));
		return ret;
	}
}st;

void AddLine()
{
	int x1 = Read() + M,y1 = Read(),x2 = Read() + M,y2 = Read();
	double k,b;
	if(x1 == x2) k = 0,b = Max(y1,y2);
	else k = 1.0 * (y2-y1) / (x2-x1),b = y1 - k * x1;
	st.Add(1,1,M<<1,Min(x1,x2),Max(x1,x2),line(k,b,1));
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read(); Q = Read();
	for(int i = 1;i <= n;++ i) AddLine();
	for(; Q ;-- Q)
	{
		int opt = Read();
		if(!opt) AddLine();
		else 
		{
			double ans = st.Query(1,1,M<<1,Read()+M);
			if(ans == -M) Put(0,'\n');
			else printf("%.2f\n",ans);
		}
	}
	return 0;
}