題目想知道的是最長嚴格下降子串行的最少個數用以覆蓋完n個數。也就是最小鏈覆蓋問題了。
那麼,我們反過來想,最長反鏈,我們求得最長不遞減序列的個數,如題,「2 4 3 1 5」中「2 4 5」就是最長的不遞減系列了,那麼,從2、4、5中各個點起飛是不是就可以覆蓋完整個鏈了,所以這就是最長反鏈了。
然後,現在就是想知道,我們刪除乙個元素會不會使得最長反鏈的長度下降乙個?也就是使得答案變成「ans - 1」?那麼,我們就是要看這一位是否對這個最長反鏈造成了貢獻,或者換句話說,能不能有另外的元素可以替換它目前的位置。
那麼,計算這層貢獻,肯定是從最後的一位開始算的,我們先給「n+1」(end位置)先附上乙個比其餘所有元素都大的值(離散化之後)。我們現在從後往前查詢到每一位,(因為我們查它在反鏈中的所能表示的位置是從前往後查的),然後,如果說我們這一位會對後面造成貢獻,那麼也就是說我們可以查到乙個在最長反鏈中表示的位置是它「+1」並且值還需要大於等於它的數的位置。
每乙個元素在最長反鏈中的貢獻:如果說它在最長反鏈中的位置是最大值是不是比它大或者等於,那麼統計它的貢獻,在
然後最後的答案一定是ans或者是ans-1,ans代表了不刪除任意元素時候的最長反鏈的長度。是否「-1」取決於它是否對最長反鏈有貢獻,並且是否不可被替換。
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define inf 0x3f3f3f3f
#define half (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define lson lsn, l, mid
#define rson rsn, mid+1, r
#define ql lson, ql, qr
#define qr rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxn = 1e6 + 7;
int n, h[maxn], lsan[maxn], _up;
int tim[maxn] = , deep[maxn], del[maxn] = , mx[maxn] = ;
bool flag[maxn] = ; //有沒有用到對應位置的元素
struct bit_tree_max
; inline void update(int x, int val) }
inline int query(int x) return sum; }
inline void re_update(int x, int val) }
inline int re_query(int x) return sum; }
} t;
int main()
sort(lsan + 1, lsan + n + 1);
_up = (int)(unique(lsan + 1, lsan + n + 1) - lsan - 1);
for(int i=1; i<=n; i++) h[i] = (int)(lower_bound(lsan + 1, lsan + _up + 1, h[i]) - lsan);
_up++;
int ans = 0;
for(int i=1; i<=n; i++)
mx[ans + 1] = _up;
for(int i=n; i>=1; i--)
}for(int i=1; i<=n; i++) if(flag[i]) tim[deep[i]]++;
for(int i=1, det = 0; i<=n; i++)
return 0;
}
演算法設計與分析 最小鏈乘
鏈乘問題 兩個矩陣相乘要求第乙個矩陣的列數等於第二個矩陣的行數,計算量主要由進行乘法運算的次數決定。採用標準的矩陣相乘演算法,計算am n bn p,需要m n p次乘法運算。矩陣相乘滿足結合律,多個矩陣相乘,不同的計算順序會產生不同的計算量。以矩陣a110 100,a2100 5,a35 50三個...