noip模擬賽 排列

2022-05-01 09:30:09 字數 1753 閱讀 7249

【問題述】

給出乙個隨機的排列,請你計算最大值減最小值的差小於等於0~n-1的區間分別有多少個。

輸入檔名為sum.in。

第一行乙個數t(<=10),表示資料組數

對於每一組資料:

第一行乙個數n(1<=n<=100,000)

第二行n個數a1...an,表示乙個隨機的排列

【輸出】

輸出檔名為sum.out。

對於每組資料輸出n行,分別表示差值小於等於0~n-1的區間個數

【輸入輸出樣例】

sum.in

sum.out

3 2 4 1

【資料說明】

對於30%的資料,1<=n<=300;

對於60%的資料,1<=n<=5000

對於100%的資料,1<=n<=100000

分析:考慮暴力,o(n^2)列舉區間,o(n)求最值,可以過30分.

如何把n^3優化到n^2?我們可以在找最值的時候優化一下,我們並不一定非要在固定了區間後再去找最值然後更新當前區間,而是我們先固定左端點,然後從左往右擴充套件去找最值,用最值更新區間資訊.

比如,我們已經求得當前區間的最小值minx和最大值maxx,向右擴充套件一位得到新的minx和maxx,那麼ans[maxx - minx]++.當然,我們也可以用st表o(1)維護最值,複雜度也是o(n^2)的.

題目資料範圍很明顯提示複雜度要o(nlogn),考慮怎麼優化60分的演算法.我們向右跳並不需要每次只跳一位,因為可能有很多位置不會更新minx和maxx,我們需要找到下一位能更新minx和maxx的位置,利用單調棧來記錄.維護乙個單調上公升的單調棧和乙個單調下降的.因為這是乙個隨機的排列,所以差不多會跳logn次.

#include #include 

#include

#include

using

namespace

std;

int t,n,a[100010],nextmin[100010],nextmax[100010],head,pos[100010],p[100010

],minx,maxx;

long

long ans[100010

];int

main()

p[++head] =a[i];

pos[head] =i;

}memset(pos,

0, sizeof

(pos));

head = 0

; memset(p,

0x3f3f3f, sizeof

(p));

for (int i = 1; i <= n; i++)

p[++head] =a[i];

pos[head] =i;

}for (int i = 1; i <= n; i++)

else}}

for (int i = 1; i < n; i++)

ans[i] += ans[i - 1

];

for (int i = 0; i < n; i++)

printf(

"%lld\n

", ans[i]);

}return0;

}

noip模擬賽 密碼

表示沒看懂演算法3 問題描述 有壓迫,就有反抗。mored的寵物在法庭的幫助下終於反抗了。作為乙隻聰明的寵物,他打算把魔法使mored的魔法書盜去,奪取mored的魔法能力。但mored怎麼會讓自己的魔法書輕易地被盜取?mored在魔法書上設定了乙個密碼鎖,密碼鎖上有乙個問題。施以斯臥鋪魔法吧,你有...

NOIP模擬賽 老師

題目描述 一座有n層的教學樓裡有一些學生,第i 0 i n 層有studentsi個學生。你被給定了乙個數k,如果第i層有x個學生,那麼這一層需要 x k 個老師。你可以調整每個學生的樓層,但是每個學生至多只能調整一層,就是說第i層的學生只能去第i 1層 如果有的話 第i層 第i 1層 如果i 1 ...

NOIP模擬賽 分錢

題目描述 兩個人在街上撿到了一些錢,這些錢共有n張,他們等了很久也沒有等來失主,於是決定把錢平分。但錢可能無法平分。他們先把能夠平分的錢盡量先平分了,使得剩下不能平分的錢盡量少。這些不能平分的錢怎麼辦呢他?他們決定拿去賭場裡面賭一把。他們運氣太好了,那些不能平分的錢變成了雙倍,於是他們就把那個錢分了...