Noip模擬考試6 解題報告

2022-07-27 06:06:15 字數 3516 閱讀 8082

peter喜歡玩陣列。noip這天,他從jason手裡得到了大小為n的乙個正整數

陣列。peter求出了這個陣列的所有子段和,並將這n(n+1)/2個數降序排序,他想

知道前k個數是什麼。

不難想到,從最大欄位和向下更新。

用set實現

介紹一下set:用法與priority_queue基本相同,區別是,set有自動去重,而priority_queue將所有元素放入。

然後通過三元組,分別記錄權值,左端與右端。

#include#include

#include

#include

#define st first

#define se second

#define ll long long

#define mp(a,b) make_pair(a,b)

#define pr pair< ll,pair>

using

namespace

std;

sets;

ll sum;

int a[100010

];int

main()

s.insert(mp(sum,mp(

1,n)));

while(k--)

}return0;

}

2. . 奇襲

(raid.cpp\c\pas)

【問題描述】

由於各種原因,桐人現在被困在under world(以下簡稱uw)中,而uw馬上

要迎來最終的壓力測試——魔界入侵。

唯一乙個神一般存在的administrator被消滅了,靠原本的整合騎士的力量

是遠遠不夠的。所以愛麗絲動員了uw全體人民,與整合騎士一起抗擊魔族。

在uw的駐地可以隱約看見魔族軍隊的大本營。整合騎士們打算在魔族入侵

前發動一次奇襲,襲擊魔族大本營!

為了降低風險,愛麗絲找到了你,一名優秀斥候,希望你能在奇襲前對魔

族大本營進行偵查,並計算出襲擊的難度。

經過偵查,你繪製出了魔族大本營的地圖,然後發現,魔族大本營是乙個n

×n的網格圖,一共有n支軍隊駐紮在一些網格中( 不會有兩隻軍隊駐紮在一起)。

在大本營中,每有乙個k×k(1≤k≤n)的子網格圖包含恰好k支軍隊,我們

襲擊的難度就會增加1點。

現在請你根據繪製出的地圖,告訴愛麗絲這次的襲擊行動難度有多大。

【輸入格式】

第一行,乙個正整數n,表示網格圖的大小以及軍隊數量。

接下來n行,每行兩個整數,xi,yi,表示第i支軍隊的座標。

保證每一行和每一列都恰有乙隻軍隊, , 即每乙個 xi 和每乙個 yi 都是不一樣

的。【輸出格式】

一行,乙個整數表示襲擊的難度。

樣例輸入:

51 1

3 22 4

5 54 3

樣例輸出:

解題:重要資訊:保證每一行和每一列都恰有乙隻軍隊, , 即每乙個 xi 和每乙個 yi 都是不一樣

的。由此可將二維首先優化至一維。

樣例則分別為 :1 4 2 3 5

觀察發現,若某一區間最大值減最小值的差等於(這段區間的長度-1)那麼該段區間可選。

若左右端點分別為i,j,那麼 滿足的條件為 i-j+1=max[i,j]-min[i,j]。

分治演算法:

在每次solve 中,會出現兩種情況:

1、最大值與最小值都出現在同一端(l2、最大值與最小值出現不同端,處理起來就比較複雜了。

首先,lmax[i]表示從mid到i點的最大值 ,同理rmax[i]表示從mid+1到i點的最大值

lmin與rmin同理。

分情況考慮:

1、[l,mid],從l到mid 過程中lmax是下降序列,lmin 為上公升序列。

2、[mid+1,r] 從mid+1到r 的過程中rmax 是上公升序列,rmin 是下降序列。

由上面公式,設最大值出現在右端 則 j-i+1=max[j]-min[i]+1;

-->max[j]-j=min[i]-i;

還有兩個條件:max[j]>max[i],min[i]那麼對max[j]-j進行預處理 ,再用min[i]-i進行對應,o(n)處理。

在**裡再進行解釋吧。

#include#include

#include

#define ll long long

using

namespace

std;

const

int maxn = 50010

;int tax[maxn<<1

];//設定乙個桶 ,用來存放max[j]-j預處理得到的值。

int *tax=&(tax[maxn]),q[maxn];//max[j]-j會出現負值,所以將陣列開到0以下。

intlmax[maxn],lmin[maxn],rmax[maxn],rmin[maxn];

int maxx = - (1

<<30

);int minn = 1

<< 30

;ll calc(

int l,int r,int

mid)

for(int i = mid+2 ; i <= r ;++i)

//預處理max和min

for(int i = l ; i <= mid ; ++i)

//最大值與最小值出現在同一端的情況

int q=mid,p=mid+1

;

while(q1]>lmin[l])q++,tax[rmax[q]-q]++;//如果右端下乙個位置仍然大於最左端的min值,那麼當前值入桶

while(p<=r&&rmax[p];//如果當前位置小於最左端max值,那麼當前值出桶

for(int i = l ; i <= mid ; ++i)//通過min[i]-i來對應max[j]-j

//像是乙個動態右移的過程,先預處理右端所有情況針對左端最左值得情況,然後通過左端右移,來實現桶的入與出。

for (int i = mid + 1 ; i <= r ; i ++)//清空

tax[rmax[i]-i] = 0

;

return

ret;

}ll solve(

int l,int

r)//分治部分

intmain()

printf(

"%i64d\n

",solve(1

,n));

return0;

}

很有意思的一道分治題,不過對於我這種蒟蒻到不行的蒟蒻來說,只能依靠題解苟活才會寫。

3.十五數碼

(fifteen.cpp/c/pas)

給出起始順序,要求通過 0 的移動(與上下左右交換),排成以下順序:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 0

輸出最少移動次數。如果無解輸出 no。

這個單獨介紹一篇吧,看一下這個:

Noip模擬題解題報告

題目鏈結 智子 cq07年省選題 區間dp 當i j時,子串明顯只需要塗色一次,於是f i j 1。當i j且s i s j 時,可以想到只需要在首次塗色時多塗一格即可,於是f i j min f i j 1 f i 1 j 當i j且s i s j 時,我們需要考慮將子串斷成兩部分來塗色,於是需要...

11 5NOIP模擬賽解題報告

預計得分 100 40 30 170 實際得分 100 100 50 250 辣雞資料毀我青春 t1一眼不會做感覺要涼 t2好像一波折半搜尋就做完了 t3好像是神仙題不會做。打完t1暴力後去淦t2,結果最後在排序的時候把greater 寫成了greater 不過感謝辣雞資料放我一條活路。手玩了一下t...

11 5NOIP模擬賽解題報告

預計得分 100 40 30 170 實際得分 100 100 50 250 辣雞資料毀我青春 t1一眼不會做感覺要涼 t2好像一波折半搜尋就做完了 t3好像是神仙題不會做。打完t1暴力後去淦t2,結果最後在排序的時候把greater 寫成了greater 不過感謝辣雞資料放我一條活路。手玩了一下t...