這道題可以是維護凸殼,直線加入的斜率還是單調的,可以直接用單調棧維護,然後二分查詢。
但是我比較蠢,打了線段樹維護,一開始還沒打出來….
來複習一下怎麼線段樹維護凸殼值吧。
問題:我們插入若干條直線,詢問某個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 記錄的是已經對當前點做過的,但是還沒有對當前點的兒子做過的操作 嗯 我們就這樣 慢慢的退一下 嗯 標記是給兒子用的 嗯 是給兒子用的 奉獻精神 然後,對於這個題,我們可以...