JOI2020遗迹

先考虑如何计算一个序列操作n次后的结果。

注意到序列最后一个数是一定不会变的。

进一步,序列最后且“没有相同的数在它右边”的数是不会变的。

只有“有相同的数在它右边”的数会变化。

实际上,摧毁的过程可以被描述为以下代码:

vis[i]表示第i种数是否在右边出现。

for(int i=2*n;i;i--){
    while(vis[a[i]])a[i]--;
    vis[a[i]]=1;
}

这样子是正确的(不用考虑时间),是因为如果右边有一个数占据了这个数的位置,这个数一定会-1。

这样子就可以从右往左dp了。

设f[i][j]表示从i~2*n填数,数组中1~j被占据的方案数。

原文地址:https://www.cnblogs.com/cszmc2004/p/13090981.html