測試51T2 單調棧維護下凸包二分

2022-03-16 13:57:25 字數 1745 閱讀 8499

單調棧維護凸包,並在凸包上二分的一類題。

1、本題維護的每個決策點是乙個一次函式,即一條線。

2、下凸包的維護:1、斜率遞增,pop掉斜率比他大的

2、交點遞減,防止不優的線影響決策

3、**自己寫的,開始沒看std,改不出來後看了第二個while,即交點遞減,沒考慮到。

這點比較好。要相信自己也能寫出來。

詳細見注釋。

#include#define f(i,a,b) for(rg int i=a;i<=b;++i)

#define rg register

#define ll long long

#define il inline

#define pf(a) printf("%lld ",a)

#define phn puts("")

using

namespace

std;

#define int ll

#define n 500010

intread();

intn,que;

ints[n],a[n],c[n];

int min(int x,int y)

int max(int x,int y)

struct

q}b[n];

intsta[n],top,ans[n];

double

get(int i,int

j)void push(int

x)/*

* 可以證明,超過邊界的不合法的決策點不優

*/int solve(int x,int

y)if(get(sta[mid],sta[mid+1])>x-y)l=mid+1

;

else r=mid;

}

l=sta[l];

//pf(l);pf(x);pf(y);phn;

/*if(x==100&&y==7)

*/return s[y]-s[l]+(x-y+l)*a[l];

}signed main();

sort(b+1,b+que+1

);

int p=1

;

while(b[p].y==1

)

sta[top=1]=1

;

/** s[y]0-s[i]+(x-y+i)*a[i]

先判兩個端點。

*/int

i,x,y;

f(k,

2,n)

continue

; }

while(b[p].y==k)

//push(k);

}

f(i,

1,que)printf("

%lld\n

",ans[i]);

}int

read()

/*g++ 1.cpp -g

./a.out

g++ dp.cpp -g

./a.out

1010 9 1 7 4 6 8 5 2 3

104 2

100 2

6 31 4

3 51 7

100 7

5 82 9

100 10

*/

view code

關於不合法的點一定不優的證明:

我證出來了,但是懶得寫了。我要去看t3了。

51nod 1272 最大距離 單調棧

1272 最大距離 codility 基準時間限制 1 秒 空間限制 131072 kb 分值 20 難度 3級演算法題 給出乙個長度為n的整數陣列a,對於每乙個陣列元素,如果他後面存在大於等於該元素的數,則這兩個數可以組成一對。每個元素和自己也可以組成一對。例如 可以組成11對,如下 數字為下標 ...

51nod 1279 扔盤子(單調棧)

開始是直接從井口往裡扔,複雜度是o n 2 超時。然後呢,你會發現,如果井上邊的寬度小,下邊的寬度大,那麼下邊寬度多大都是沒用的,所以就讓他等於上邊寬度就好了。然後處理後這個井的寬度從上到下就是乙個非遞增的了,然後從下向上匹配,o n 還可以用單調棧預處理 include include const...

單調棧 51nod 1437邁克步

有n隻熊。他們站成一排隊伍,從左到右依次1到n編號。第i隻熊的高度是ai。一組熊指的隊伍中連續的乙個子段。組的大小就是熊的數目。而組的力量就是這一組熊中最小的高度。邁克想知道對於所有的組大小為x 1 x n 的,最大力量是多少。有n隻熊。他們站成一排隊伍,從左到右依次1到n編號。第i隻熊的高度是ai...