so就 (二分答案 dp 贪心)
来源:互联网 发布:口腔医学网络教育 编辑:程序博客网 时间:2024/05/27 14:12
so就
9.11
思路:
明显的dp感觉,但是nk的复杂度又很恼火。当然有一种二分答案然后用dp来check的方法,就贴上代码不细说了。这里还有一种贪心的做法,用一个set来维护最大权值,之后每次从堆里取出堆顶元素,每次贪心的维护k=i时的ans(就只有k次循环),将堆顶元素和相邻的两个元素合并并修改权值,用链表维护相邻的关系,具体的实现还是看代码吧。
#include <iostream> #include <cstdio>#include <set>#define LL long longusing namespace std; const int N = 100010; int n, k;LL ans, a[N];int pre[N], nex[N];struct node { LL w; int id; friend bool operator <(const node & a, const node & b){ return a.w==b.w ? a.id<b.id : a.w>b.w;} }; set<node> q;void solve() { while( k-- ){ node top = *q.begin(); q.erase((node){ top.w, top.id}); ans += (LL)a[top.id]; a[top.id] = a[pre[top.id]] + a[nex[top.id]] - a[top.id]; if( pre[top.id] ) q.erase((node){ a[pre[top.id]], pre[top.id]}); if( nex[top.id] ) q.erase((node){ a[nex[top.id]], nex[top.id]}); q.insert((node){ a[top.id], top.id}); if( pre[pre[top.id]] ) nex[pre[pre[top.id]]] = top.id; if( nex[nex[top.id]] ) pre[nex[nex[top.id]]] = top.id; pre[top.id] = pre[pre[top.id]]; nex[top.id] = nex[nex[top.id]]; } } int main(){ freopen ("so.in", "r", stdin); freopen ("so.out", "w", stdout); scanf("%d%d", &n, &k); a[0] = (LL)-1e17; for(int i=1; i<=n; i++){ scanf("%I64d", &a[i]); pre[i] = i-1, nex[i] = i+1; q.insert((node){ a[i], i}); } pre[1] = 0; nex[n] = 0; solve(); printf("%I64d", ans); return 0; }
dp
#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>using namespace std ;typedef long long LL ; int n, k ; const int MAXN = 100010 ; int a[MAXN]; LL b[MAXN] ; LL dp[MAXN][2] ;int minp[MAXN][2] ; int check(LL x) { for (int i = 1; i <= n; i ++) b[i] = x + a[i] ; for (int i = 1; i <= n; i ++) { dp[i][0] = dp[i - 1][0], minp[i][0] = minp[i - 1][0] ; if (dp[i - 1][1] > dp[i][0]) dp[i][0] = dp[i - 1][1], minp[i][0] = minp[i - 1][1] ; else if (dp[i - 1][1] == dp[i][0] && minp[i - 1][1] > minp[i][0]) minp[i][0] = minp[i - 1][1] ; dp[i][1] = dp[i - 1][0] + b[i], minp[i][1] = minp[i - 1][0] + 1 ; } if (dp[n][1] > dp[n][0]) return minp[n][1] ; if (dp[n][1] == dp[n][0]) return min(minp[n][1], minp[n][0]) ; return minp[n][0] ; }LL Calc(LL x) { for (int i = 1; i <= n; i ++) b[i] = a[i] + x; for (int i = 1; i <= n; i ++) { dp[i][0] = dp[i - 1][0], minp[i][0] = minp[i - 1][0] ; if (dp[i - 1][1] > dp[i][0]) dp[i][0] = dp[i - 1][1], minp[i][0] = minp[i - 1][1] ; else if (dp[i - 1][1] == dp[i][0] && minp[i - 1][1] > minp[i][0]) minp[i][0] = minp[i - 1][1] ; dp[i][1] = dp[i - 1][0] + b[i], minp[i][1] = minp[i - 1][0] + 1 ; } return max(dp[n][0], dp[n][1]) - 1LL * x * k ; }int main() { freopen("so.in", "r", stdin) ; freopen("so.out", "w", stdout) ; scanf("%d%d", &n, &k) ; for (int i = 1; i <= n; i ++) scanf("%d", &a[i]) ; LL l = - 10000000000LL, r = 10000000000LL ; while (l < r) { LL mid = (1LL * l + r + 20000000000LL) / 2 + 1 - 10000000000LL ; if (check(mid) > k) r = mid - 1 ; else l = mid ; } cout << Calc(l) << endl ; }
阅读全文
0 0
- so就 (二分答案 dp 贪心)
- <队内胡策> 2017.10.10 (贪心+二分答案+DP)
- BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心
- BZOJ 2067 POI 2004 SZN 树形DP 贪心 二分答案
- poj 2774 木材加工(dp/二分答案+贪心)
- [贪心 模拟 + 二分答案 DP] BZOJ 1181 [CROATIAN2009]IZBROI选举
- [BZOJ2525][Poi2011]Dynamite 二分答案+贪心+树型DP
- 【jzoj4932】【贪心】【二分答案】
- 数学题 贪心+二分答案
- poj3122 二分答案+贪心
- UVALive 4625 Garlands(二分答案 + DP)
- UVALive 3608 Period(二分答案+DP)
- 道路覆盖 (二分答案+状压DP)
- CodeVS1725 探险 【二分答案】【贪心】
- 【BZOJ3048】Cow lineup,贪心+队列维护(或二分答案)
- CODE[VS] 2744 养鱼喂妹纸 (二分答案验证 + 贪心)
- Codeforces738C-Road to Cinema(二分答案+贪心)
- luogu1084【2012提高】疫情控制(二分答案+贪心+倍增)
- Thymeleaf教程 (八) 模板布局(thymeleaf的主要技术优势)
- blktrace
- 静态代码块、构造代码块、构造函数
- 逆光 (摄影术语)
- 采用python进行Android的多渠道打包
- so就 (二分答案 dp 贪心)
- 阿里云视频点播解决方案使用教程
- 斐波那契数列求和问题
- 计算程序运行时间 C语言
- C#WinForm的 Window 消息大全
- Android Dagger2入门详解(三)
- 爬格子呀4-8
- 进制转换
- java war 打包、解压命令