bzoj_5416_[noi2018]氣泡排序_dp+組合數+樹狀陣列
好題。合法的排列的交換次數剛好是交換次數的下界,也就是說不能有多餘的交換。
也就是對於ai這個數,只能從i到ai這乙個方向走。
考慮x,y,z三個數(x>y>z),y需要和x、z各交換一次,這顯然不能使y這個數滿足只向乙個方向移動這個條件。
於是轉化為排列的連續下降子串行最多為2。
考慮dp,設f[i][j]表示最後i個數沒填,這i個數中有j個數是大於字首(1~n-i)最大值的方案數。
考慮倒數第i個數可以填什麼,f[i][j]<---f[i-1][k],有k<=j。
當k==j時說明填入了乙個小於字首最大值的數,這樣的數隻可以填最小的乙個,有一種方案。
當k有dp式子f[i][j]+=f[i-1][k](0<=k<=j),即f[i][j]=f[i-1][j]+f[i][j-1]。
然後考慮對已知的這個排列怎麼做。
假設字首最大值為mx,現在處理到的這一位排列上的值是p。
如果p>mx,這一位可以從p+1開始取值。
否則,p+1到mx的這些數不能選,如果選了會和前面的mx和後面的p形成3元組。
故這一位考慮max(mx,p)+1開始的數,比較好的一件事就是這些數一定都沒出現,那麼對答案的貢獻就是$\sum\limits_^f[n-i][j]$。
這玩意又等於f[n-i+1][n-max(mx,p)-1]。
還要注意每步如果p我們現在的時間複雜度到了$o(n^2)$,發現複雜度瓶頸在求f那裡。
考慮dp方程f[i][j]=f[i-1][j]+f[i][j-1],相當於把所有(x,y)(x這玩意就是用推卡特蘭數的方式翻摺計數可得f[i][j]=c(i+j,i)-c(i+j,i+1)。
然後就做完啦。
**:
#include #include #include using namespace std;#define n 600050
#define mod 998244353
#define _max(x,y) ((x)>(y)?(x):(y))
typedef long long ll;
inline char nc()
int rd()
int fac[n<<1],inv[n<<1],n,p[n],c[n];
int qp(int x,int y)
void fix(int x,int v)
int inq(int x)
void init()
int c(int n,int m)
int f(int i,int j)
void solve()
printf("%d\n",ans);
}int main()
刷題 BZOJ 5415 Noi2018 歸程
考試的時候打的可持久化並查集,沒調出來qaq 後面知道了kruskal重構樹這個東西,感覺好簡單啊 這道題就建出kruskal重構樹後,對於兩個點找到它們的lca,其子樹min就是答案 include define ui unsigned int define ll long long define...
bzoj 5417 NOI2018 你的名字
神題啊.首先我們考慮68分的暴力 對於詢問串的每個位置 i 我們維護乙個 lim 表示以 i 為終點向前至多能與模式串匹配多長,這一點可以在把詢問串放在模式串的字尾自動機上跳躍得到 接下來考慮統計答案 對於詢問串同樣建起乙個字尾自動機,我們知道字尾自動機上的每個節點維護的位置是一些長度連續的子串,同...
NOI2018 氣泡排序
noi2018 氣泡排序 題解性質 模型轉化 首先,乙個排列是 好 的,當且僅當 每個數,要麼是字首最大值,要麼是字尾最小值。討論i和pi的關係即可證明 也就是,排列不能存在 3的下降子串行!換句話說,假設之前填了i個數,最大值是mx,那麼第i 1個數,要麼是剩下數的最小值,要麼是比mx大的數。字典...