雜項

hutongzhou發表於2024-05-01

一些好的部落格/技巧

學習部落格

1.斜率最佳化 包含斜率最佳化的兩種做法,一些例題。

2.static關鍵字用法詳解

3.FFT

技巧

1.對於大量字串輸入的辦法:stringstream 講解

2.當一道題的數量超過 __int128 ,又不想寫高精時,就可以用到 long double,它的範圍在:\(1.2 \times 10^-4932 ~ 1.2 \times 10^4932\),雖然會掉精度,但對於:\(10 ^ {1000}\) 的資料還是綽綽有餘。輸出時要注意處理,因為如果直接輸出 double 型別,就會出現:

//型別一:整數位很多
double x=12345678;
//型別二:小數位很多,有效小數位少
double y=0.00001234;

cout<<x<<endl;
cout<<y<<endl;

輸出:

1.23457e+07
1.234e-05

我們要不讓他輸出科學計數法,可以加上 fixed 語句,然後要讓它不保留小數部分,加上 setprecision(0)

詳見:詳解C++中fixed,setprecision(),setw()的用法

例題:P2687 [USACO4.3] 逢低吸納Buy Low, Buy Lower

4.有關矩陣運算題的處理

  • 把矩陣都封裝在結構體中
struct matrix{
	int a[5][5];
	void init()
	{
		
	}
	void .......
	{
    
	}
	.......
};
  • 初始化都是單位矩陣 \(I\)

可以封裝在結構體中。

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

如可以手寫出來可以用 const直接定義,會快一點。

const matrix I
{{
        {1,0,0,0,0},
        {0,1,0,0,0},
        {0,0,1,0,0},
        {0,0,0,1,0},
        {0,0,0,0,1}	
}};
  • 矩陣乘法可以用自定義符號方便的求出,這也封裝在結構體裡。
matrix operator*(const matrix y)const
{
	matrix c;
	c.init();
	for(int i=0;i<=4;i++)
	for(int j=0;j<=4;j++)
	for(int k=0;k<=4;k++)
	c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*y.a[k][j]%mod)%mod;
	return c;
}

也可以在外面過載運算子:

matrix operator*(const matrix &a,const matrix &b)const
{
	matrix c;
	c.init();
	for(int i=0;i<=4;i++)
	for(int j=0;j<=4;j++)
	for(int k=0;k<=4;k++)
	c.x[i][j]=(c.x[i][j]+1ll*a.x[i][k]*b.x[k][j]%mod)%mod;
	return c;
}
  1. 關於樹的直徑的求法

先隨便找一個點求每個結點的深度,然後把最深的那個結點作為根,再變數一遍,樹的深度為直徑。

求直徑的路徑:只用記錄每個點的父親,然後找到最深的那個結點一直向上找即可(就是一個單向連結串列)。

void dfs(int *dd ,int u,int fa)
{
	from[u]=fa;
	dd[u]=dd[fa]+1;
	for(int v : g[u])
	{
		if(v==fa)	continue;
		dfs(dd,v,u);
	}
}
int main()
{
	dfs(d,1,0);
	for(int i=1;i<=n;i++)	if(d[st]<d[i])	st=i;
	dfs(d,st,0);
	for(int i=1;i<=n;i++)	if(d[ans]<d[i])	ans=i;
	int len=d[ans];
	while(len--)	cout<<ans,ans=from[ans];
}

易錯點

  1. 多測不清空,oi 一場空,但清空陣列時注意範圍,是清空 \(1\)\(n\),還是 \(0\)\(m\)

  2. 有些題看似不用卡 long long,但在某些很小的地方要開。如特判時的語句時:

if(n*m>s)  return ;

\(n*m\) 爆了,要開 long long

if((long long)n*m>(long long)s)  return ;
  1. 莫隊中四個 while 迴圈的順序

保證正確的原則是 l<=r(注意\(l,r\)的大小順序)。

最好記的是先擴大,也就是 --l, ++r,然後再縮小l++,r--

   while (l > a[i].l) add(c[--l]);
   while (r < a[i].r) add(c[++r]);
   while (l < a[i].l) del(c[l++]);
   while (r > a[i].r) del(c[r--]);

還有其他的一種
oi wiki


排序方式

一定要看清楚判斷的先後級,是比較塊的大小還是本身端點的大小,每個莫隊的比較方式不一樣。

還有要看清楚結構體的編號。

錯誤示範(來源)
P1903 [國家集訓隊] 數顏色 / 維護佇列)

bool cmp(node2 a,node2 b)
{
	if(be[a.l]!=be[b.l])return be[a.l]<be[b.l];
	if(be[a.r]!=be[a.r])return be[a.r]<be[a.r]; 
	//改成 if(be[a.r]!=be[b.r])return be[a.r]<be[b.r];
	return a.t<b.t;
}

相關文章