CEOI2015 Day2 核能國度 題解

2022-06-12 19:57:16 字數 4096 閱讀 4429

\(~~~~\) 給出 \(w \times h\) 的矩形,\(n\) 個修改,每個修改有位置及引數 \(a,b\) ,表示對其周邊距離它切比雪夫距離為 \(d\) 的格仔的權值增加 \(\max(0,a-b\times d)\) 。最後 \(q\) 組詢問,每次求乙個子矩陣的和。

\(~~~~\)

我不會告訴你我做這道題做了半個月並且實現還借助了題解。(雖然有一周在期末考試。

\(~~~~\) 每次暴力修改其影響到的格仔的權值,每次查詢暴力求子矩陣的和,這個不多說。

\(~~~~\) 期望得分:???

\(~~~~\) 暴力修改權值後做一遍二維字首和,每次查詢 \(\mathcal(1)\) 回答。

\(~~~~\) 期望得分:\(\texttt\)

\(~~~~\) 觀察到有 \(\texttt\) 給在 \(h=1\) ,那麼此時整個矩形可以被看作是一排數。設某個橫座標為 \(x\) 的修改能影響到的最遠的距離 \(\dfrac=d\) ,那麼就相當於給 \([x-d,x]\) 加上乙個首項為 \(a \bmod b\) ,公差為 \(b\) ;給 \([x+1,x+d]\) 加上乙個首項為 \(a-b\) ,公差為 \(-b\) 的等差數列。

\(~~~~\) 此時套路地維護這個數列的差分數列,那麼需要支援區間加法,單點修改,且詢問在所有修改之後。因此用差分維護差分數列,還原後再用一維字首和回答即可。

\(~~~~\) 期望得分:結合 solution 2 可得 \(\texttt\)(部分子任務重合)。

\(~~~~\) 你已經想到用差分維護一維差分數列了,那麼我們來隨便舉個例子看二維的情況:

\(~~~~\) 這是乙個 \(a=7,b=2\) 的例子,(雖然畫錯了),但不難看出在差分後的規律:

\(~~~~\bullet\) 左上和右下角為 \(a \bmod b\),右上和左下角為 \(- a \bmod b\) 。

\(~~~~\bullet\) 除開四角,主對角線全為 \(b\) ,副對角線全為 \(-b\) 。

\(~~~~\) 當然直接根據差分的式子也能得到這個規律,這裡為了直觀就用找規律了。

\(~~~~\) 那麼我們暴力 (指 o(1)) 修改四角,然後差分維護對角線即可。

\(~~~~\) 時間複雜度:\(\mathcal(n+wh+q)\) 。

\(~~~~\) 期望得分:結合 solution 2 和 solution 3 可得 \(\texttt\) 。

\(~~~~\) 這裡貼乙個我寫了三次才寫出來的僅能得新增的 \(\texttt\) 的**:

檢視**

#include #include #include #define ll long long

using namespace std;

const ll maxn=2500005;

ll n,m,k,q;

struct array}pre,dia1,dia2;//用指標開陣列

int main()

for(ll j=1;j<=m;j++) }

for(ll j=1;j<=m;j++) for(ll i=1;i<=n;i++) pre[i][j]+=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];

ll q;scanf("%lld",&q);

while(q--)

return 0;

}

\(~~~~\) 事實上 ,上面演算法的時間複雜度是對的,但它並不能得全分。如果你仔細觀察題目,你會看到這樣一句話:

\(~~~~\) 如果核電站位於核能國的邊境或是在離邊境稍近的位置,那麼**可能也會影響到核能國之外的方格。影響到核能國外方格的**被稱作界限

\(~~~~\) 而上面 solution3.5 新增的 \(\texttt\) 來自沒有界限的子任務。仔細思考一下,我們會發現如果**影響到的格仔在當前矩形的左、左上或上方時,差分標記會影響內部的值,但如果出界了我們統計不到那部分。

\(~~~~\) 而且本題我們無法通過擴大若干倍矩形來強行統計那些部分,考慮乙個極端情況:\(w=h=1\) ,然後在那個格仔上有乙個 \(a=2^,b=1\) 的修改。

\(~~~~\)以下涉及大量**實現,其中\(n\),\(m\)是題面中\(w\)\(h\)

\(~~~~\) 那麼我們分別對每一種標記來考慮怎麼處理出界的問題:

\(~~~~\) 對於四角的修改,我們強行移動它到對應的第乙個生效的位置即可,換句話說就是把小於 \(1\) 的座標移動到 \(1\) :

檢視**

void tag(ll x1,ll y1,ll x2,ll y2,ll v)

tag(max(x-up,1ll),max(y-up,1ll),min(x+up,n),min(y+up,m),a%b-b);//呼叫,注意後面即使對答案不影響也不能不取min,否則會re。

// 最後對於四角-b,則整個對角線都+b即可

\(~~~~\) 對於主對角線的修改,我們將其超出部分的全部移動到第一行或第一列對應的位置,這個需要分類討論幾種情況。

\(~~~~\) 先寫乙個給第一行/列打標記的函式:

檢視**

ll a[maxn],b[maxn];//記超出部分給 第一行 和 第一列 打的標記 

void sign(ll *arr,ll l,ll r,ll v) //一階差分,對 [l,r] +v ,記在第一行或第一列

\(~~~~\) 然後對超出的左上角部分進行處理:

檢視**

void taglu(ll x1,ll y1,ll x2,ll y2,ll v)//[x1,y1]:起始 [x2,y2]:最後乙個超出的格仔

else if(y2<=0)//area 3:上 }

taglu(x-up,y-up,x-min(min(x-1,y-1),up)-1,y-min(min(x-1,y-1),up)-1,b);

\(~~~~\) 以及打起始和結束的標記:

檢視**

dia1[x-min(min(x-1,y-1),up)][y-min(min(x-1,y-1),up)]+=b;

dia1[x+1+min(up,min(n-x-1,m-y))+1][y+1+min(up,min(n-x,m-y-1))+1]-=b;

\(~~~~\) 然後是副對角線,大體同上,但注意左右都可能有超出。

檢視**

void tagru(ll y1,ll y2,ll v)

void tagld(ll x1,ll x2,ll v)

void tag(ll x,ll y,ll a,ll b)

\(~~~~\) 最後把對角線的差分標記還原,把第一行和第一列歸到一起

檢視**

for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) dia1[i][j]+=dia1[i-1][j-1],dia2[i][j]+=dia2[i-1][j+1];

for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) dia1[i][j]+=dia2[i][j];

for(int i=1;i<=n;i++) dia1[i][1]+=(a[i]+=a[i-1]);

for(int i=1;i<=m;i++) dia1[1][i]+=(b[i]+=b[i-1]);

\(~~~~\) 然後就和上面沒有任何區別了。輕鬆而又愉快。

\(~~~~\) 時間複雜度:同 solution3.5

\(~~~~\) 期望得分:\(\texttt\) 。

\(~~~~\) 完整**就不貼了,整體很醜。

CEOI2015 Day2 世界冰球錦標賽

題目描述 譯自 ceoi2015 day2 t1 ice hockey world championship 今年的世界冰球錦標賽在捷克舉行。bobek 已經抵達布拉格,他不是任何團隊的粉絲,也沒有時間觀念。他只是單純的想去看幾場比賽。如果他有足夠的錢,他會去看所有的比賽。不幸的是,他的財產十分有限...

TJOI2015 Day2解題報告

在一棵n 10 5的樹上要求支援 從a點走到b點,求最大的value j value i 其中i,j是點,i在路徑中出現的位置先於j。將a b路徑上每個點的value加上v。自然可以用樹鏈剖分 lct做。每一段區間存四個數 後減前 型的最大值fmx,前減後 型的最大值bmx 這是由於有時候區間可能會...

NOIP2015 Day2 運輸計畫

公元 2044 年,人類進入了宇宙紀元。l 國有 n 個星球,還有 n 1 條雙向航道,每條航道建立在兩個星球之間,這 n 1 條航道連通了 l 國的所有星球。小 p 掌管一家物流公司,該公司有很多個運輸計畫,每個運輸計畫形如 有一艘物流飛船需要從 ui 號星球沿最快的宇航路徑飛行到 vi 號星球去...