追逐學長的背影 2023年10月

2022-05-07 23:15:23 字數 3754 閱讀 3964

加油啊布丁醬

跳過了乙個lis的隨筆。(lis類似公升序的單調佇列,有模板的題先不看了)

先按x的大於序排序,再按y的大於序排序。從第乙個點開始找,記錄當前最大的y,每次新的y比當前y大的時候更新y。 $o(nlogn)$ 

首先看到這裡的直覺就是總電量的一半(因為是連續的,所以可以通過幾顆電池去削減大電池的電量,構成兩個相等的電池之後可以輪流削減兩個相等的電池的電量指直到自己的電量耗完,再把兩顆剩餘的相等的電池耗完,這樣就證明每三顆(比較平均的)電池都可以完全利用,類似的思路可以猜測都是可以完全削減的),但是我少考慮了一種情況,就是有一顆超大的電池,要把其他的電池都和他匹配。

這麼小的資料量可以用字首和,暴力列舉每個子矩陣查詢 $o(n^4)$ 。學長也是用暴力列舉的,不知道他怎麼卡過去的。搜了一下解法,可以壓縮乙個維度,比如先用字首和支援了 $o(1)$ 查詢,然後 $dp[i][j][k]$ 表示以 $(i,j)$ 為右下角,高度為 $k$ 的最大子矩陣,那麼每次從左到右轉移的時候, $dp[i][j][k]=dp[i][j-1][k]>=0?(dp[i][j-1][k]+sum(i,j,k)):sum(i,j,k))$ ,也就是最長上公升子串的dp方法,這樣是 $o(n^3)$ 。

資料量太小了導致可以直接sort,而先用nth_element()之後還是要sort(因為資料量太大不能桶排序)。

可以使用歸併排序的修改來統計逆序數,也就是先分治,然後右邊的每次出隊的時候,這個元素對應的逆序數就是左邊佇列中剩餘的元素的數量,之前的那道題突然就會解決了!布丁醬加油!

#include#include

using

namespace

std;

int a[100010]= ,l[100010]= ,r[100010]= ;

long

long ans=0

;#define m 1000000000;

void gb(int left,int mid,int

right)

else

}}void gbsort(int left,int

right)

}int

main()

view code

我的想法是,先求導變成二次方程,然後用求根公式求出二次方程的根,那麼三次方程的極大值點和極小值點就確定了。根據極大值和極小值是否包夾著x軸可以判斷有多少個根,在有根的區間內三次方程是單調的可以用二分法求出零點。類似的思路我們可以解出四次方程的交點……雖然討論一定很複雜就是了。注意單調性對二分的影響。

慣性思維想用map,但其實sort一下就可以了。

學長真強,我是入坑一年多才學的。

#include#include

#include

#include

#include

using

namespace

std;

vector

g[100010

];int father[100010][40]= ;

int depth[100010]= ;

intn,m;

bool visit[10010]= ;

introot;

void dfs(int

u) }}//

深搜出各點的深度,存在depth中

void

bz()

//倍增,處理father陣列,詳情參照上述講解

int lca(int u,int

v) //

保證深度大的點為u,方便操作

int dc=depth[u]-depth[v];

inti;

for (i=0; i<30; i++)

//上述操作先處理較深的結點,使兩點深度一致

if (u==v)

return u;//

如果深度一樣時,兩個點相同,直接返回

for (i=29; i>=0; i--)

}u=father[u][0];//

上述過程做完,兩點都在lca下一層,所以走一步即可

returnu;}

intmain()

depth[root]=1

; dfs(root);

bz();

intx,y;

scanf(

"%d%d

",&x,&y);

printf("%d

",lca(x,y));

return0;

}

view code

這個肯定是可以搜尋解法的,每次列舉有沒有雷然後驗證。感覺搜尋很快就會返回。然後我們知道,假如已知兩個方格和第二個方格正下方的數字,可以唯一確定第三個格的數量,所以dfs是只會一路向前搜尋的,不會再有分支。

由鵬哥賽馬的啟發,最菜的肯定是去消耗對方最厲害的。最菜的那個平局的情況,有兩種思路,要麼去消耗對方最厲害的,有可能避免自己隊得0分……還是太亂了。

這道題就是田忌賽馬,策略很簡單,如果當前最差的能比對方當前最差的強,就讓當前最差的與對方最差的比(顯然當前已經是最差的了,在能戰勝對方最差的前提下,肯定是出動己方越差的越好);如果不滿足,則比較當前最強的和對方最強的,如果比對方強則直接對比。

如果都不滿足,就考慮用己方最差的直接與對方最強的比,這顯然是可行的,反正己方對上對方最強的都不能勝利,那麼還不如用自己最差的去換掉對方最強的。

還有一種情況,就是存在相同的時候呢?強的相同,那看看弱的那個會不會輸,弱的那個會輸則交換。否則不交換。弱的相同,則看看強的會不會輸,強的會輸則交換,否則不交換。但是這為什麼一定是最優的呢?

其實假如先把最大的最小的能打的都打了,剩下的交換就一定不會更差。

前向星:可能比vector好的寫法,但是可能會比vector難寫。把所有邊按 $(u,v)$ 排序,那麼所有同起點的邊都在一起了,然後遍歷一次找到同起點的邊的右邊界,儲存left[i]和right[i],那麼 $[edge[left[i]],edge[right[i]])$ 就是所有從 $i$ 出發的邊。

更簡單的是next陣列。

鏈式前向星:head[i]表示以i為結尾的最後一條邊的位置,e.next[j]表示第j條邊的下一條兄弟邊的位置。在add_edge(u,v)的時候只需要 e.to=v;e.next[cnt]=u;head[u]=cnt;cnt++; 初始化為-1,然後搜尋的時候 for(int i=head[u];i!=0;i=edge[i].next) 就可以了,這裡預設edge[0]不放任何東西!也就是邊從1開始計數。

自己做題多累啊,看別人的題解輕鬆又愉快,之前我為什麼一直要堅持不看呢?先看別人做提公升一定實力再說吧。

這個看學長的思路是貪心,先按結束時間排個序(再按耗時短排序可以減少後面的比較),然後假如當前的建築可以修好,就修,否則從已經修好的乙個建築中選乙個耗時最長的(假如比當前這棟更長)放回等待的佇列(的隊首,所以要雙端佇列),因為這樣修好的建築數量不變但是結束時間提前了所以更好。已經修好的建築就用堆來維護就好了。

學長說是dfs判環……的確沒毛病。假如出現了(不從外面進來的)環,環就是最大/最小值。假如沒有出現環,那就是幾條鏈,鏈全部連起來就是最大值,最長的鏈就是最小值。

上面的分析是錯的。環中的某個位置也可以是同類的人!從外面進來的環,也可以貼到環裡面(指向同乙個節點的兩個節點必定收縮),最後會收縮出一些環和一些鏈。鏈可以任意摺疊還可以連到環上,毫無影響。

所以k必然是每個環的約數,那就是最大公約數和》=3的最小公約數啦!還有一些細節先不想了。

2023年10月書單推薦

窮人在懷疑中拒絕,富人在懷疑中了解!就是實實在在的有對應的技術對應的能力 本書適合精讀。對於單元測試的整體的概念和分類講的不錯,適合新手對單元測試概念的惡補。而且也有對應的例子和工具,總的來說,相當不錯。當然用的語言是c 可以忽略語言本身,注意陳述的知識即可。本書適合速讀。其中單元測試編寫的細則分類...

2023年10月之 嘰裡咕嚕

一看是11月1日才寫的這個10月總結就知道這兩天滾成球了。這週末codestorm 51nod演算法馬拉松 bc cf hihocoder,然後還有乙個華山杯的ctf 其實這些比賽自己比得有些超出自己預期,有的極其爛。像51,之前一直都是爆零大隊大隊長,這次一下子做出兩個80分的題,尤其是選數字那題...

2023年7月29日 Windows 10正式發布

對於微軟來說,今天是乙個特別的日子 windows 10全球正式發布了。與以往的windows發布不同的是,windows 10公升級對已有的windows 7和windows 8的使用者是完全免費的。如果你用的是台式電腦沒有觸控螢幕,你的體驗將和windows 7,而不是windows 8,更接近...