JZOJ5390 維護直線

2021-08-08 20:45:33 字數 1807 閱讀 9061

這道題可以是維護凸殼,直線加入的斜率還是單調的,可以直接用單調棧維護,然後二分查詢。

但是我比較蠢,打了線段樹維護,一開始還沒打出來….

來複習一下怎麼線段樹維護凸殼值吧。

問題:我們插入若干條直線,詢問某個x的最大函式值。

方法:對於線段樹乙個點x,假設他代表區間為[l,r]下標代表自變數的值,中點為mid,他的兩個兒子代表的區間是[l,mid-1]和[mid+1,r]。我們在這個節點只儲存一條直線,滿足他在mid是的函式值最大。

插入直線l1的時候,假如這個點沒有直線,那麼把這條直線存在這裡,退出。如果有直線l2,我們要分情況討論。yl

1(mi

d)2(mi

d),那麼如果kl

12 ,把l1遞迴進[l,mid-1],否則進入[mid+1,r]。為什麼這麼做呢?因為,l1在遞迴進去的區間裡,l1有可能在一部分地方比l2大;而另外乙個區間是不可能的。即使l1在任何地方都比l2差,傳進去也沒問題,因為我們已經儲存了l2,查詢的時候會碰到他,而l1有可能比l2好,我們不能放過這種可能性。yl

1(mi

d)>yl

2(mi

d),把上面的兩條直線反過來即可,並且讓x這個點儲存l1。

查詢自變數x的時候,我們一直遞迴進區間(x,x)(不存在就可能是因為他是某個mid),路上碰到的每條直線都更新一下答案。整體來看,這樣做是對的。當然這個方法有些資訊維護不了,更強大的方法要用平衡樹。

因為卡空間,我把自變數映**一下。

#include
#include

#include

#include

#include

using namespace std;

#define cmax(a,b) (a=(a>b)?a:b)

#define fo(i,j,k) for(i=j;i<=k;i++)

#define fd(i,j,k) for(i=j;i>=k;i--)

typedef long long ll;

typedef double db;

const int n=4e5+5,mo=1e9+7;

struct rec

b[n];

bool operator

int d[n],v[n],vt,tr[n*2];

ll prt[n],ans,mx=4e18;

int n,m,i,j,k;

void clear()

void change(int

x,int l,int r,int

y) int mid=(l+r)/2;

ll vx=1ll*v[mid]*b[tr[x]].x+b[tr[x]].y,vy=1ll*v[mid]*b[y].x+b[y].y;

if (vx>vy)// down vy

else

}void get(int

x,int l,int r,int

y)int main()

fo(i,1,m)

sort(b+1,b+1+n+m);

sort(d+1,d+1+m);

fo(i,1,m) if (d[i]!=d[i-1]) v[++vt]=d[i];

fo(i,1,n+m)

}clear();

fd(i,n+m,1)

else

}fo(i,1,m) printf("%lld\n",prt[i]);

}

CSUOJ 1258 維護序列

線段樹題目。此題的更新必須要更新到葉節點,否則的話,會出現錯誤。對於乙個int範圍內的數字,更新若干次 最多32次 後必然會變成0,那麼此時在更新就沒有意義了。那麼我們可以用lazy標記,當某個區間的數字全部變為0後,我們將這個區間做上標記。那麼這個區間就不可能在被更新,這樣就可以提高效率,減去不必...

bzoj 2453 維護佇列

你小時候玩過彈珠嗎?小朋友a有一些彈珠,a喜歡把它們排成佇列,從左到右編號為1到n。為了整個佇列鮮豔美觀,小朋友想知道某一段連續彈珠中,不同顏色的彈珠有多少。當然,a有時候會依據個人喜好,替換佇列中某個彈珠的顏色。但是a還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你來尋求幫助。輸入檔案第一...

BZOJ 1798 維護序列

線段樹 這 d 道 q 題 s 告訴我說 你沒學過線段樹 嗯 這題要好好想想 qaq 來吧首先要明確的事情是 delta now 記錄的是已經對當前點做過的,但是還沒有對當前點的兒子做過的操作 嗯 我們就這樣 慢慢的退一下 嗯 標記是給兒子用的 嗯 是給兒子用的 奉獻精神 然後,對於這個題,我們可以...