1. 程式人生 > 其它 >XIN隊演算法

XIN隊演算法

從luogu的blog搬過來了

XIN隊演算法

注:名稱由莫隊演算法改編而來

從luogu搬過來了。。。

\(newly\;upd:2021.7.8\)

\(newly\;upd:2021.6.6\)

OI至高演算法,只要XIN隊演算法打滿,保證所有比賽 \(rk1\),碾爆標程,讓對手望塵莫及。

請慎用

XIN隊演算法:

1.遇到不會做的題目不用慌,你要想到你還有XIN隊演算法,仔細讀題,理解題目意義,然後開始準備寫XIN隊演算法。

2.這時候,你可以瀟灑地敲出:

void xin_team()

然後開始暴搜

XIN隊演算法框架:

    void xin_team(引數)
    {
        if(邊界) return;
        for(register int i=1;i<=n;++i)
            if(條件1)
            {
                狀態轉移
                xin_team(引數);
                狀態回溯
            }
    }

但是,對於不同的題目, void xin_team 並不能解決所有的題目,那該怎麼辦呢???

對於很多不能用XIN隊\(1\)號演算法的,大多數可以使用XIN隊\(2\)號演算法:
next_permutation(a+1,a+n+1); 大法

框架:


    void xin_team2
    {
        do
        {
            答案記錄
        }while(next_permutation(a+1,a+n+1));
    }

非常完美

但是,由於XIN隊演算法時間複雜度 只有 \(\mathcal O(2^n)\)或者是\(\mathcal O(n!)\)

,所以我們提出優化:

優化XIN隊演算法:

非常不建議使用

框架:

        srand((unsigned)time(0));
        do
        {
            random_shuffle(a+1,a+n+1);
            答案記錄
        }while(next_permutation(a+1,a+n+1));

複雜度:

\[\mathcal O(\lim_{1\to\infty}) \]

還附加超大常數

XIN隊演算法升級:二維XIN隊

有很多很多的題目無法用普通的\(XIN\)隊演算法解決,這時候我們就需要\(XIN\)隊演算法升級版:\(\color{red}\huge_{\text{二維XIN隊}}\)

二維\(XIN\)隊對於程式碼能力的提升是顯而易見的,然而對複雜度的提升更是顯而易見的,二維\(XIN\)隊演算法框架:

比方說:

[SDOI2015]排序

使用此演算法,輕鬆 \(30pts\)

	void xin_team2(int x,int now)
	{
		if(邊界) 
		{
			xin_team2(x,now);
			記錄
			return ;
		}
		for(register int i=1;i<=n;++i)
		{
			記錄狀態
			xin_team(x,now+1);
			回溯狀態
		}
	}
	void xin_team1(int x,int now)
	{
		if(邊界) 
		{
			xin_team2(x,now);
			記錄
			return ;
		}
		for(register int i=1;i<=n;++i)
		{
			記錄狀態
			xin_team(x,now+1);
			回溯狀態
		}
	}

複雜度:

\[\mathcal O(n! * 2^n) \]

並且只能說是大概

我們發現,對於一般的題目,大多是 \(dp\) 解決,然而純粹運用上述方法只能拿到部分分數,甚至全部 \(TLE\) 所以,記憶化 \(XIN\) 隊演算法應運而生。


對於優秀的記憶化 \(XIN\) 演算法,想要什麼狀態就去找什麼狀態,然後就可以實現飛一般的提升。。。

包準快

使用記憶化 \(XIN\) 隊演算法,\(NOI\)包準不打鐵!

比方說這個題: \(NOI2020\)美食家

使用 \(XIN\) 隊演算法,輕輕鬆鬆 \(40pts\)

框架:

	void xin_team(int i,int j)
	{
		if(f[i][j]) return f[i][j];
		for(k ...)
			xin_team(k,~);
		return f[i][j];
	}

演算法的時間複雜度就是:

\[\mathcal O (\prod_{i=1}^{n} state_{num_i}) \]

\(num\)為狀態,複雜度總體海星。。。

然而:

\(\color{red} \huge{\text{方程推不出}}\)

\(\color{green} \huge{\text{親人兩行淚}}\)





\(XIN\) 優化分塊預處理

一個月沒更了,這次在刷題的時候發現了最新的 \(XIN\) 隊演算法應用

這是在寫蒲公英的時候發現的。

做了好長時間,中途還跑去做樹鏈去了。


時間相差的確實長了一些。。。

在用分塊解決這個問題的時候。

發現狂 \(T\) 不止。

但是。

不知道為什麼在其他的 \(OJ\) 上都可以過掉

只不過就是很慢。

但是在學校的 \(OJ\) 上最多隻有 \(70pts\)

好評測機

然而並不敢找老師去開大時限

所以我只能優化暴力。。。

然後。

我發現在預處理 \(p_{i,j}\) 的時候,時間差的很多很多。

然而如果用 \(query\) 函式而不是暴力去搞就會錯。。。

因為有些需要的狀態還沒有附上值但是接下來處理需要用到。。。

所以我集中生智

發現了 \(XIN\) 隊優化分塊預處理法

我都沒想到 \(XIN\) 隊演算法還有優化別的東西的一天

主要思想就是 缺啥找啥

然後狀態就有了。。。

雙指標突然不香了 \(\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\) --搖擺兵

然後飛快

	void xin_team(int x,int y)
	{
		if(p[x][y]) return;
		if(abs(y - x) <= 2) {p[y][x] = p[x][y] = query(l[x],r[y],0); return;}
		xin_team(x+1,y-1);
		p[x][y] = p[y][x] = query(l[x],r[y],0);
	}

\(\color{red}{\huge{\uparrow \text{精華}}}\)

\(\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\huge{record}\)