單調棧維護凸包,並在凸包上二分的一類題。
1、本題維護的每個決策點是乙個一次函式,即一條線。
2、下凸包的維護:1、斜率遞增,pop掉斜率比他大的
2、交點遞減,防止不優的線影響決策
3、**自己寫的,開始沒看std,改不出來後看了第二個while,即交點遞減,沒考慮到。
這點比較好。要相信自己也能寫出來。
詳細見注釋。
#include#define f(i,a,b) for(rg int i=a;i<=b;++i)view code#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
*/
關於不合法的點一定不優的證明:
我證出來了,但是懶得寫了。我要去看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...