uoj 213 UNR 1 爭奪聖杯 單調棧

2021-08-19 11:48:32 字數 1012 閱讀 7074

給出乙個長度為n的序列a,對於乙個m,定義該序列的價值為a[1]到a[m]的最大值+a[2]到a[m+1]的最大值+…+a[n-m+1]到a[n]的最大值。求當m取[1,n]時對應的價值。 n≤

106n ≤10

6考慮每個元素對答案的貢獻。當取最大值時,我們把權值看做第一關鍵字,下標看做第二關鍵字,這樣每個子串行就唯一對應乙個最大值。

對於每個元素,我們找到它左邊和右邊第乙個比它大的元素的位置,那麼當這個元素做貢獻時,對應的子串行就不能跨過比它大的元素。

設這個元素可以作貢獻的區間長度為len,那麼它對ans的貢獻係數必然是形如1 2 3 3 3 3 2 1的數列,只要用二階差分統計下就好了。

#include

#include

#include

#include

#include

const

int n=1000005;

const

int mod=998244353;

const

int inf=2000000000;

int n,a[n],stack[n],lef[n],rig[n],ans[n];

int read()

while (ch>='0'&&ch<='9')

return x*f;

}void mod(int &x)

void pre()

top=0;stack[++top]=n+1;

for (int i=n;i>=1;i--)

}int main()

for (int i=2;i<=n;i++) mod(ans[i]+=ans[i-1]);

for (int i=2;i<=n;i++) mod(ans[i]+=ans[i-1]);

int w=0;

for (int i=1;i<=n;i++) w^=ans[i];

printf("%d",w);

return

0;}

線段樹 單調棧 UNR 1 爭奪聖杯

用單調棧求出left right 可以發現每個點的貢獻是關於left right的分段函式 然後就是分段函式累加求和 當時打的線段樹 看了題解漲姿勢了 可以差分 做到o n include include includeusing namespace std typedef pairabcd typ...

UOJ 218 UNR 1 火車管理

維護一顆主席樹 火車入棧相當於區間修改,彈棧相當於返回歷史版本 維護線段樹區間求和 ps 之前沒把 放上來 extra的最後乙個點re,orz蒟蒻無能為力 include include include include include const int maxn 600005 const int ...

UOJ 218 UNR 1 火車管理

注意記憶體有些卡,有一些技巧 1.首先對於查詢的線段樹是全域性的,不需要動態開點 2.對於線段樹中的乙個節點 x 如果它的左右兒子都沒有兒子,那麼下一次做區間覆蓋時,就不需要對 x 新建兩個節點 include define lo o 1 define ro o 1 1 using namespac...