CF #439 E Another Maximum Problem

本文解析了CF#439E Another Maximum Problem问题,并通过分治策略优化原始DP算法的时间复杂度。文章介绍了如何利用决策单调性进行优化,详细解释了分治递归过程和成本计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CF #439 E Another Maximum Problem

分治·决策单调性

题解:

暴力Dp:

f[i][j]表示前i个分成j段的最小花费。

f[i][j]=f[k][j1]+cost(k+1,i)

cost=icnt[i](cnt[i]1)2

时间复杂度:O(n2k)

优化:

决策具有单调性。

(打表?)

那这个单调性怎么用呢?

以前做过一个单调队列维护决策区间的。

但是那样要求能快速计算出cost,而这里的cost显然要维护。

那就分治。

[L,R]表示当前分治的区域,它由[l,r]转移过来。

先解决一下[L,R]的mid从那里转以来,记为p,

然后向下分治:solve(l,p,L,mid-1),solve(p,r,mid+1,r)

那么如何计算cost呢?

像莫队那样维护。

一个lpos指针一个rpos指针表示当前统计的区间,根据需要移动两个指针。

调用solve前保证lpos=l-1,rpos=L-1。

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
typedef long long ll;
const int N = 2e5+5;

int n,a[N],cnt[N]; ll f[21][N];

void solve(int l,int r,int L,int R,int K,ll cur){
    if(L>R) return;
//  D(l); D(r); D(L); D(R); D(K); D(cur); E;
    int mid=(L+R)>>1, p;
    for(int i=L;i<=mid;i++) cur+=cnt[a[i]]++;
    for(int i=l;i<=mid && i<=r;i++){
        cur-=--cnt[a[i]];
        if(f[K][mid]>f[K-1][i]+cur){
            f[K][mid]=f[K-1][i]+cur; p=i;
        }
    }
//  D(mid); D(p); D(f[K][mid]); E;
    for(int i=L;i<=mid;i++) cur-=--cnt[a[i]];
    for(int i=l;i<=mid && i<=r;i++) cur+=cnt[a[i]]++;
    solve(l,p,L,mid-1,K,cur);
    for(int i=L;i<=mid;i++) cur+=cnt[a[i]]++;
    for(int i=l;i<p;i++) cur-=--cnt[a[i]];
    solve(p,r,mid+1,R,K,cur);
    for(int i=L;i<=mid;i++) cur-=--cnt[a[i]];
    for(int i=l;i<p;i++) cur+=cnt[a[i]]++;
}

int main(){
    freopen("6.in","r",stdin);
    int n,K; ll cur=0;
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++){
        cur+=cnt[a[i]]++;
        f[1][i]=cur;
    }
    for(int i=2;i<=K;i++){
        memset(cnt,0,sizeof(cnt));
        solve(1,n,1,n,i,0);
    }
    printf("%lld\n",f[K][n]);
}
CF818G Four Melodies 题目描述 Author note: I think some of you might remember the problem “Two Melodies” from Eductational Codeforces Round 22. Now it’s time to make it a bit more difficult! Alice is a composer, and recently she had recorded two tracks that became very popular. Now she has got a lot of fans who are waiting for new tracks. This time Alice wants to form four melodies for her tracks. Alice has a sheet with � n notes written on it. She wants to take four such non-empty non-intersecting subsequences that all of them form a melody and sum of their lengths is maximal. Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements. Subsequence forms a melody when each two adjacent notes either differ by 1 or are congruent modulo 7. You should write a program which will calculate maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody. 输入格式 The first line contains one integer number � n ( 4 < = � < = 3000 4<=n<=3000 ). The second line contains � n integer numbers � 1 , � 2 , . . . , � � a 1 ​ ,a 2 ​ ,...,a n ​ ( 1 < = � � < = 10 5 1<=a i ​ <=10 5 ) — notes written on a sheet. 输出格式 Print maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody. 输入输出样例 #1 输入 #1 5 1 3 5 7 9 输出 #1 4 输入输出样例 #2 输入 #2 5 1 3 5 7 2 输出 #2 5 说明/提示 In the first example it is possible to compose 4 4 melodies by choosing any 4 4 notes (and each melody will consist of only one note). In the second example it is possible to compose one melody with 2 2 notes — 1 , 2 1,2 . Remaining notes are used in other three melodies (one note per each melody). 代码: C++ #include <bits/stdc++.h> using namespace std; class MinCostMaxFlow { public: MinCostMaxFlow(int n, int s, int t) : n(n), s(s), t(t) { head.assign(n + 1, -1); } void add_edge(int u, int v, int w, int c) { e.push_back(Edge{v, w, c, head[u]}); head[u] = e.size() - 1; e.push_back(Edge{u, 0, -c, head[v]}); head[v] = e.size() - 1; } bool SPFA() { now.assign(head.begin(), head.end()); dis.assign(n + 1, INF); inq.assign(n + 1, false); queue<int> q; dis[s] = 0, q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); inq[u] = false; for (int i = head[u]; ~i; i = e[i].nxt) { int v = e[i].to; if (e[i].w > 0 && dis[v] > dis[u] + e[i].c) { dis[v] = dis[u] + e[i].c; if (!inq[v]) q.push(v), inq[v] = true; } } } return dis[t] != INF; } int dfs(int u, int sum, int& cost) { if (u == t) return sum; int flow = 0; for (int i = head[u]; ~i && sum > 0; i = e[i].nxt) { int v = e[i].to; if (e[i].w > 0 && dis[v] == dis[u] + e[i].c) { int tmp = dfs(v, min(sum, e[i].w), cost); if (!tmp) dis[v] = INF; e[i].w -= tmp, e[i ^ 1].w += tmp; sum -= tmp, flow += tmp; cost += tmp * e[i].c; } } return flow; } pair<int, int> Dinic() { int maxflow = 0, mincost = 0; while (SPFA()) maxflow += dfs(s, INF, mincost); return make_pair(maxflow, mincost); } private: const int INF = 1e9; struct Edge {int to, w, c, nxt; }; int n, s, t; vector<Edge> e; vector<int> head, now, dis; vector<bool> inq; }; const int INF = 1e9; const int MAX_N = 3050; int n, a[MAX_N]; int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; int s0 = n * 2 + 1, s = n * 2 + 2, t = n * 2 + 3; MinCostMaxFlow mcmf(n * 2 + 3, s0, t); mcmf.add_edge(s0, s, 4, 0); for (int i = 1; i <= n; i++) { mcmf.add_edge(s, i, INF, 0); mcmf.add_edge(i, i + n, 1, -1); mcmf.add_edge(i + n, t, INF, 0); for (int j = i + 1; j <= n; j++) if (a[i] % 7 == a[j] % 7) { mcmf.add_edge(i + n, j, INF, 0); mcmf.add_edge(i, j, INF, 0); break; } for (int j = i + 1; j <= n; j++) if (a[i] + 1 == a[j]) { mcmf.add_edge(i + n, j, INF, 0); break; } for (int j = i + 1; j <= n; j++) if (a[i] - 1 == a[j]) { mcmf.add_edge(i + n, j, INF, 0); break; } for (int j = i + 1; j <= n; j++) if (a[i] == a[j]) { mcmf.add_edge(i, j, INF, 0); break; } } auto ans = mcmf.Dinic(); cout << -ans.second << &#39;\n&#39;; return 0; } 为什么在第二个样例死循环了
08-06
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是一个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是一个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值