[jzoj]4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰(线段树优化DP)
来源:互联网 发布:李炎恢php 百度网盘 编辑:程序博客网 时间:2024/06/11 10:48
https://jzoj.net/senior/#contest/show/2156/1
Problem
题目大意:
给定一段序列,要求把一段序列分成若干段,保证每一段里没有重复的原子,且一段的贡献值为这一段中最大的中子数.
求最小贡献和.
Solution
设
f[i] 表示到第i 个数的最小贡献和.显然有:
f[i]=min{f[j]+s[j+1][i]} 我们考虑用线段树去维护.
首先,一个
b[i] ,考虑到它能更新到的最大范围,是k∼i ,其中k 是第一个大于等于b[i] 的b[k] .那么,把这一段贡献到线段树上,便是
min{f[k..i]}+b[i] .每次查询,直接查一段的最优解即可.
后续:
- 这里,注意要维护
f 的最小值,以及一段区间的最优答案,更新最优答案时,可以直接用一个区间的最小f ,加上这段区间被更新的sum .
- 这里,注意要维护
#include <iostream>#include <cstdio>#include <cstring>const int Maxn = 1e5 + 10, maxn = 1e4 + 10, Maxni = 2 * 1e5 + 10;using namespace std;int n,ans,maxni;int a[Maxn],b[Maxn],f[Maxn],g[Maxn],t[Maxn],bz[Maxn];int fmin[Maxni*4],fmax[Maxni*4],tree[Maxn*4],lzy[Maxn*4];void lazy(int x,int y) { tree[y] = lzy[x] + fmin[y], lzy[y] = lzy[x]; }void lbzy(int x,int y) { fmin[y] = lzy[y] = lzy[x]; }void find(int x,int st,int en,int l,int r,int p){ if ((l <= st) && (en <= r)) { if (p==-1) ans = min(ans,tree[x]); else if (p==-2) ans = max(ans,fmax[x]); else tree[x] = p + fmin[x], lzy[x] = p; return; } if (lzy[x] > 0) lazy(x,x << 1),lazy(x,(x << 1) + 1), lzy[x] = 0; int mid = (st + en) >> 1; if (mid>=l) find(x << 1,st,mid,l,r,p); if (mid< r) find((x << 1) + 1,mid+1,en,l,r,p); tree[x] = min(tree[x << 1],tree[(x << 1) + 1]);}void modify(int x,int st,int en,int p,int q){ if (st==en) fmin[x] = q; else { int mid = (st + en) >> 1; if (mid >= p) modify(x << 1,st,mid,p,q); else modify((x << 1) + 1,mid+1,en,p,q); fmin[x] = min(fmin[x << 1],fmin[(x << 1) + 1]); }}void modifx(int x,int st,int en,int p,int q){ if (st==en) fmax[x] = q; else { int mid = (st + en) >> 1; if (mid>=p) modifx(x << 1,st,mid,p,q); else modifx((x << 1) + 1,mid+1,en,p,q); fmax[x] = max(fmax[x << 1],fmax[(x << 1) + 1]); }}int main(){ freopen("array.in","r",stdin), freopen("array.out","w",stdout); scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%d%d",&a[i],&b[i]), maxni = max(maxni,b[i]); g[0] = 1, memset(fmin,7,sizeof(fmin)), memset(tree,7,sizeof(tree)), find(1,0,n,0,0,0), modify(1,0,n,0,0); for (int i = 1; i <= n; i++) { g[i] = g[i-1], ans = 0, find(1,1,maxni,b[i],maxni,-2), t[i] = ans, modifx(1,1,maxni,b[i],i); if (bz[a[i]]==0) bz[a[i]] = i; else g[i] = max(g[i],bz[a[i]] + 1), bz[a[i]] = i; } for (int i = 1; i <= n; i++) { ans = 1e9, find(1,0,n,t[i],i,b[i]); //把当前这一段"新"的 值给更新一下 ans = 1e9, find(1,0,n,g[i]-1,i-1,-1); //找到answer(g[i]-1,i-1) f[i] = ans, modify(1,0,n,i,f[i]); //单点修改f } printf("%d",f[n]);}
阅读全文
0 0
- [jzoj]4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰(线段树优化DP)
- jzoj 4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰 动态规划+线段树
- jzoj 4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- JZOJ 4883 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- 【JZOJ4883】【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- JZOJ4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
- JZOJ4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰 2017.10(B组)
- jzoj 4882. 【NOIP2016提高A组集训第12场11.10】多段线性函数 乱搞
- JZOJ 4882 【NOIP2016提高A组集训第12场11.10】多段线性函数
- jzoj 4887. 【NOIP2016提高A组集训第13场11.11】最大匹配 树形dp
- jzoj 4890. 【NOIP2016提高A组集训第14场11.12】随机游走 树上期望dp
- JZOJ 4841【NOIP2016提高A组集训第4场】平衡的子集
- JZOJ 4826. 【NOIP2016提高A组集训第2场10.30】小澳的葫芦
- NOIP2016提高A组集训第12场11.10 总结
- jzoj 4832. 【NOIP2016提高A组集训第3场10.31】高维宇宙 网络流或状压dp
- 【NOIP2016提高A组集训第12场11.10】图的半径
- JZOJ4884. 【NOIP2016提高A组集训第12场11.10】图的半径
- 使用ssh config配置文件来管理ssh连接
- 悬浮按钮
- 八大排序算法之(一)插入排序 直接插入排序
- Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json
- Java集合三之Vector
- [jzoj]4883. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰(线段树优化DP)
- C++实习笔记(1)
- 研究生如何找到一份数据挖掘的工作
- GTK实现:扫雷源代码(saolei.c)
- 设置环境变量
- J
- [JSOI2008]最大数maxnumber
- codeforces—— 869E —— The Untended Antiquity
- redis命令行基本操作