Bzoj 3688 折線統計(dp 樹狀陣列)

2022-05-01 03:33:08 字數 2715 閱讀 8316

開始以為同樣斜率的折線算一條,後來經過大佬提示發現是假的,那就很簡單了

這是一道比較基礎的資料結構優化 \(dp\) 的問題

首先按照 \(x\) 座標排序

首先能夠想出 \(dp\) 狀態

\(dp[i][j][0/1]\) 表示前 \(i\) 個數,選了 \(j\) 段,當前折線是上公升/下降的

腦補可得轉移方程:

\[f[i][j][0]=\sum\limits_^f[k][j][0]+f[k][j-1][1] (if~y_k>y_i)\\

f[i][j][1]=\sum\limits_^f[k][j][1]+f[k][j-1][0] (if~y_k

上述方程 \(i\) 這一維每一次只和前面的元素有關,那麼就可以通過資料結構優化轉移

由於有 \(y\) 的限制,不能使用字首和,那麼考慮樹狀陣列

建出 \(2*k\) 棵樹狀陣列記錄 \(f\) 陣列的值,轉移即可

前面那個直接查詢,後面那個字首和一下就行

時間複雜度 \(o(n~k~log~n)\)

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std ;

#define int long long

#define rep(i, a, b) for (int i = (a); i <= (b); i++)

#define per(i, a, b) for (int i = (a); i >= (b); i--)

#define loop(s, v, it) for (s::iterator it = v.begin(); it != v.end(); it++)

#define cont(i, x) for (int i = head[x]; i; i = e[i].nxt)

#define clr(a) memset(a, 0, sizeof(a))

#define ass(a, sum) memset(a, sum, sizeof(a))

#define lowbit(x) (x & -x)

#define all(x) x.begin(), x.end()

#define ub upper_bound

#define lb lower_bound

#define pq priority_queue

#define mp make_pair

#define pb push_back

#define fi first

#define se second

#define iv inline void

#define enter cout << endl

#define siz(x) ((int)x.size())

#define file(x) freopen(#x".in", "r", stdin),freopen(#x".out", "w", stdout)

typedef long long ll ;

typedef unsigned long long ull ;

typedef pair pii ;

typedef vector vi ;

typedef vector vii ;

typedef queue qi ;

typedef queue qii ;

typedef set si ;

typedef map mii ;

typedef map msi ;

const int n = 100010 ;

const int inf = 0x3f3f3f3f ;

const int iinf = 1 << 30 ;

const ll linf = 2e18 ;

const int mod = 100007 ;

const double eps = 1e-7 ;

void print(int x)

void print(string x)

void douout(double x)

int n, k, mx, ans ;

pii a[n] ;

int f[n][12][2], g[12][2][n] ;

void add(int bit[n], int x, int y)

int ask(int bit[n], int x)

signed main()

sort(a + 1, a + n + 1) ;

rep(i, 1, n)

ans = (ans + f[i][k][0] + f[i][k][1]) % mod ;

} printf("%lld\n", ans) ;

return 0 ;}/*

寫**時請注意:

1.ll?陣列大小,邊界?資料範圍?

2.精度?

3.特判?

4.至少做一些

1.最大值最小->二分?

2.可以貪心麼?不行dp可以麼

3.可以優化麼

4.維護區間用什麼資料結構?

5.統計方案是用dp?模了麼?

6.逆向思維?

*/

bzoj3688 折線統計

time limit 10 sec memory limit 256 mb submit 119 solved 66 submit status discuss 二維平面上有n個點 xi,yi 現在這些點中取若干點構成乙個集合s,對它們按照x座標排序,順次連線,將會構成一些連續上公升 下降的折線,設...

BZOJ3688 折線統計

portal time limit 10 sec memory limit 256 mb 二維平面上有n個點 xi,yi 現在這些點中取若干點構成乙個集合s,對它們按照x座標排序,順次連線,將會構成一些連續上公升 下降的折線,設其數量為f s 如下圖中,1 2,2 3,3 5,5 6 數字為下圖中從...

bzoj3688 折線統計

二維平面上有n個點 xi,yi 現在這些點中取若干點構成乙個集合s,對它們按照x座標排序,順次連線,將會構成一些連續上公升 下降的折線,設其數量為f s 如下圖中,1 2,2 3,3 5,5 6 數字為下圖中從左到右的點編號 將折線分為了4部分,每部分連續上公升 下降。現給定k,求滿足f s k的s...