洛谷 P1627 中位數 遞推 字首和思想

2021-07-24 14:33:44 字數 1770 閱讀 6730

題目描述

給出1~n的乙個排列,統計該排列有多少個長度為奇數的連續子串行的中位數是b。中位數是指把所有元素從小到大排列後,位於中間的數。

輸入輸出格式

輸入格式:

第一行為兩個正整數n和b,第二行為1~n的排列。

【資料規模】

對於30%的資料中,滿足n≤100;

對於60%的資料中,滿足n≤1000;

對於100%的資料中,滿足n≤100000,1≤b≤n。

輸出格式:

輸出乙個整數,即中位數為b的連續子串行個數。

輸入輸出樣例

輸入樣例#1:

7 4

5 7 2 4 3 1 6

輸出樣例#1:

4題解:一道思路題。我一開始的思路是利用字首和,維護兩個字首和陣列,maxx[i]和minn[i],分別表示1到i這個點之間一共有多少比b大的數和多少比b小的數。那i~j之間比b大的數就可以用ma

xx[j

]−ma

xx[i

−1] 得到。最後列舉區間,複雜度是o(

n/4)

。這樣只能過8個點。

正解:記錄下b的位置k,第一次迴圈從k+1到n迴圈,到該數大於b時,f[

i]=f

[i−1

]+1 ,反之f[

i]=f

[i−1

]−1 ,如果f[

i]==0

則ans

++,然後用乙個陣列p記錄p[

f[i]

]++ ,表示記錄該數出現了多少次。

然後從k-1到1迴圈,同樣用f[i]記錄。然後an

s+=p

[f[i

]],f陣列含義就是遇到比b大的數就+1,遇到小的數就-1,那麼如果b的左右兩邊出現同乙個f[i],那麼說明這兩個位置之間比b大的數的個數等於比b小的數的個數,那麼直接更新答案。複雜度是o(

n).

注意,因為c++陣列下標不為負數,所以開陣列是把所有下標統一加上100000,保證下標為正,同時注意陣列大小也要相應增加100000。

orz

#include

#include

#define s 100000

using

namespace

std;

int a[200006],k,ans=0,n;

int b,minn[200006],maxx[200006],p[200006],f[200006];

int get()

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

return x*z;

}void work()

else

if (a[i]1]+1;maxx[i]=maxx[i-1];}

else

if (a[i]==b)

}}void love()

}}void distance()

else

p[f[i]]++;

if (f[i]==s)

ans++;

}for (i=k-1;i>=1;i--)

else

ans+=p[s+s-f[i]];

if (f[i]==s)

ans++;

}printf("%d",ans+1);

}int main()

f[k]=s;

if (n<=1000)

distance();

}

洛谷 P1627 中位數

原題 考場想到了正解,但是依舊選擇了暴力,這究竟是天意,還是人覺啊!為了表示內心的惋惜與痛卻,還寫什麼解題思路啊!找到指定數的位置,算一遍字首和 如果a i include include include include include include include include include...

洛谷P1627 CQOI2009 中位數

給出1 n的乙個排列,統計該排列有多少個長度為奇數的連續子串行的中位數是b。中位數是指把所有元素從小到大排列後,位於中間的數。第一行為兩個正整數n和b,第二行為1 n的排列。資料規模 對於30 的資料中,滿足n 100 對於60 的資料中,滿足n 1000 對於100 的資料中,滿足n 100000...

洛谷 P1168 中位數

題目描述 給出乙個長度為n的非負整數序列a i 對於所有1 k n 1 2,輸出a 1 a 2 a 2k 1 的中位數。color red 即 color 前1,3,5,個數的中位數。輸入輸出格式 輸入格式 輸入檔案median.in的第1行為乙個正整數n,表示了序列長度。第2行包含n個非負整數a ...