相當於走出兩條路線,將所有數包含,使得每條路線都是單調增的。
為了方便我們加入p[0]=0和p[n+1]=n+1。
設f[i]表示一條路線(沒有指定是第一條路線)走到了i-1,另一條路線走到了i,滿足條件的方案數。
邊界是f[1]=1,答案是f[n+1]*2(兩條路線實際上不可區分但原題中可區分那麼它們可以交換即乘2)。
如何轉移呢?在i的路線會包含一段區間[i,j],而不包含j+1,則j+1被處在i-1的路線包含,然後就可以轉移到f[j+1]。
需要滿足的條件是[i,j]單增,p[
i−1]
j+1]
。 可以預處理next[i]表示最大的j滿足[i,j]單增,next陣列有單調性。
那麼這就是暴力dp了。
我們按順序掃。
當我們做出f[i]後,接下來可以轉移到的j必須滿足p[
j+1]
>p[
i−1]
j<=ne
xt[i
]
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10,mo=998244353;
int ad[maxn*4];
int h[maxn],go[maxn],nxt[maxn];
int ask[maxn][3];
int id[maxn],a[maxn],next[maxn],f[maxn];
int i,j,k,l,t,n,m,tot,top;
intread()
while (ch>='0'&&ch<='9')
return
x*f;
}void add(int
x,int
y)void mark(int p,int v)
void down(int p)
}void change(int p,int l,int r,int a,int b,int v)
down(p);
int mid=(l+r)/2;
if (b<=mid) change(p*2,l,mid,a,b,v);
else
if (a>mid) change(p*2+1,mid+1,r,a,b,v);
else
}int query(int p,int l,int r,int a)
int main()
f[1]=1;
fo(i,1,n+1)
if (i>1) f[i]=query(1,0,n+1,a[i]);
if (i>n) break;
top++;
ask[top][0]=a[i-1]+1;
ask[top][1]=n+1;
ask[top][2]=f[i];
add(next[i]+2,top);
change(1,0,n+1,a[i-1]+1,n+1,f[i]);
}(f[n+1]+=mo)%=mo;
printf("%d\n",f[n+1]*2
%mo);
}
bzoj 4515 遊戲 樹鏈剖分 線段樹
先讓我 一發lych大佬點我去看dalao的題解 講的很詳細.這裡糾正乙個地方,lych大佬的式子中有乙個 a d s d x b a d x b a d s 應該是 a d s d x b a d x b a d s 看來是大爺敲式子的時候敲錯了.除去這個就很完美啦 新get了線段樹標記永久化的姿...
BZOJ5005 桌球遊戲 線段樹 並查集
如果乙個區間的端點在區間內,則這個區間可以走到那個區間,詢問乙個區間能否到另乙個區間。首先我們立馬想到了 如果兩個區間嚴格有交集,那麼這兩個區間所能到達的區間集合是一樣的。那麼如果兩個區間嚴格有交集的話我們就可以把它們合併起來,這裡運用並查集。這樣處理完之後,剩下的區間只有兩種情況 包含或者相離。那...
BZOJ 4756 線段樹合併(線段樹)
思路 1.最裸的線段樹合併 2.我們可以觀察到子樹求乙個東西 那我們直接dfs序好了 入隊的時候統計一下有多少比他大的 出的時候統計一下 減一下 搞定 線段樹合併 by siriusren include include include using namespace std const int n...