====== CF Edu Round 94 ====== ===== D ===== **题意:**给定一个序列最大长度为3e3,问有多少个四元组$(i,j,k,l)$满足$i #include #include #include #include #include #include using namespace std; typedef long long ll; int read() { int x = 0, flag = 1; char c = getchar(); while ((c > '9' || c < '0') && c != '-') c = getchar(); if (c == '-') flag = 0, c = getchar(); while (c <= '9' && c >= '0') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } return flag ? x : -x; } const int MAX = 3e3 + 10; int pic[MAX]; pair seg[MAX * MAX]; int tot; ll dp[MAX][MAX]; inline void init(int n) { tot = 0; for (int i = 0; i <= n;i++) memset(dp[i], 0, sizeof(ll) * (n + 1)); } int main() { int t = read(); while(t--) { int n = read(); ll ans = 0; for (int i = 1; i <= n;i++) pic[i] = read(); for (int i = 1; i ===== E ===== **题意:**积木大赛变种,新增操作,把一堆积木去掉任意个。数据范围5e3 **题解:**开始想成dp写到后面发现完全不是dp就是一个贪心,对于一个区间的积木,要么一个个的全都去掉,要么让最小值直接去掉,然后递归计算两边。由于要取区间最小值,所以我当时写了个线段树,后来发现完全不需要,这个不是个dp,整个复杂度不是$n^2$,因为每次贪心会使得区间长度减一,所以复杂度是$O(n)$的,所以即便是暴力取最小值,也不过是$n^2$的复杂度,完全可以过。(所以这题数据范围还可以加强) #include #include #include #include #include #include #define ls (node << 1) #define rs ((node << 1) | 1) using namespace std; const int MAX = 5e3 + 20; int read() { int x = 0, flag = 1; char c = getchar(); while ((c > '9' || c < '0') && c != '-') c = getchar(); if (c == '-') flag = 0, c = getchar(); while (c <= '9' && c >= '0') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } return flag ? x : -x; } int mmin[MAX << 2]; int pic[MAX]; int dp[MAX][MAX],n; inline int get_min(int x,int y) { if (pic[x] < pic[y]) return x; else return y; } void build(int node,int l,int r) { if (l == r) { mmin[node] = l; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); mmin[node] = get_min(mmin[ls] , mmin[rs]); } inline int qurry(int node, int l, int r, int L, int R) { if (l == L and r == R) return mmin[node]; else { int mid = (L + R) >> 1; if (r <= mid) return qurry(node << 1, l, r, L, mid); else if (l >= mid + 1) return qurry((node << 1) | 1, l, r, mid + 1, R); else return get_min(qurry(node << 1, l, mid, L, mid) , qurry((node << 1) | 1, mid + 1, r, mid + 1, R)); } } int mfs(int l,int r,int mins) { if (l>r) return 0; if (dp[l][r] != -1) return dp[l][r]; if (l == r and pic[l] - mins <=0) return 0; int pos = qurry(1, l, r, 1, n); int ann = min(r - l + 1, mfs(l, pos - 1, pic[pos]) + mfs(pos + 1, r, pic[pos]) + pic[pos]-mins); dp[l][r] = ann; return ann; } int main() { n = read(); memset(dp, -1, sizeof(dp)); for (int i = 1; i <= n;i++) pic[i] = read(); build(1, 1, n); cout << mfs(1, n,0); }