数据结构优化dp
本以为自己的dp已经成熟了没想到在优化上面还是欠佳 或者是思路方面优化dp还不太行。

赤壁之战 当然 很有意思的题目描述 大体上是苦肉计吧 。盖黄 ...
题意是 求出长度为m的严格上升子序列的个数 这个还比较基础。阶段比较明显。
f[i][j] 表示前i个数字当中选出了j个数字的方案数 显然的状态转移是 f[i][j]+=f[k][j-1](a[k]<a[i]&&1<=k<i)
枚举状态 n^2 枚举决策 k O(n) 总复杂度 n^3 这样看起来是过不了这道题的。
考虑如∑快速寻找决策注意我们只要值不要k这个下标所以 线段树 树状数组搞一搞即可。
复杂度 n^2logn (注意将a[i]进行离散)没了。(注意循环顺序)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
#define ll long long
#define max(x,y) (x>y?x:y)
#define min(x,y) (x>y?y:x)
#define mod 1000000007
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<?putchar('-'),x=-x:;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=;
int n,m,T,top,ans;
int a[MAXN],b[MAXN],c[MAXN];
int f[MAXN][MAXN];//f[i][j] 表示前i个数字当中选出j个数字的方案数
//f[i][j]+=f[k][j-1](a[k]<a[i])
void discrete()
{
top=;
sort(a+,a++n);
for(int i=;i<=n;++i)if(i==||a[i]!=a[i-])a[++top]=a[i];
for(int i=;i<=n;++i)b[i]=lower_bound(a+,a++top,b[i])-a;
}
void add(int x,int y)
{
for(;x<=top;x+=x&(-x))c[x]=(c[x]+y)%mod;
return;
}
int ask(int x)
{
int cnt=;
for(;x;x-=x&(-x))cnt=(cnt+c[x])%mod;
return cnt%mod;
}
int main()
{
//freopen("1.in","r",stdin);
T=read();
for(int w=;w<=T;++w)
{
memset(f,,sizeof(f));
n=read();m=read();ans=;
for(int i=;i<=n;++i)b[i]=a[i]=read(),f[i][]=;
discrete();
for(int j=;j<=m;++j)
{
memset(c,,sizeof(c));
for(int i=;i<=n;++i)
{
int xx=ask(b[i]-);
f[i][j]=(f[i][j]+xx)%mod;
add(b[i],f[i][j-]);
}
}
for(int i=m;i<=n;++i)ans=(ans+f[i][m])%mod;
printf("Case #%d: %d\n",w,ans);
}
return ;
}
算是很水的一道题目。

这道题是一个 什么东西 我首先想到一个O(n)的dp
f[i][0/1]表示到达第i个栅栏在其左端或者在其右端已经经过的最小距离。
显然 f[i][0]=min(f[i][0],min(f[i-1][1]+|y[i-1]-x[i]|,f[i-1][0]+|x[i]-x[i-1|);
或 f[i][1]=min(f[i][1],min(f[i-1][1]+|y[i-1]-y[i]|,f[i-1][0]+|y[i]-x[i-1|);
仔细观察貌似不太对 因为对于其他决策 1=<j<i 来说也是可以转移到i 的所以貌似这个不太对。
我继续想 有了 f[i][j] 表示到达第i个栅栏的第j个位置的最小价值
转移 f[i][j]=min(f[i][j],f[i-1][k]+|j-k|); 这个好,明显转移时正确的 因为是最优子结构嘛。
当然也显然 这个dp转移不太友好就算我将其坐标进行离散化 复杂度也是n^3的
显然 n^2的都不太能过别说n^3的了,我可以优化:
拆开绝对值 f[i][j]=min(f[i][j],f[i-1][k]+j-k);(k<=j) f[i][j]=min(f[i][j],f[i-1][k]+k-j) k>j
j为已知 不管 f[i-1][k]-k显然是具有单调性的单调队列优化寻找决策 里面存着最小的k这个决策即可。
对于k>j同理 神奇的发现这 优化到了n^2 非常有意思。
我好想能拿到绝大多数分了 但是这依然是在超时的边缘的。不管了我已经尽力了。
正解是这样的 对于第二个dp 这个状态是不优的 因为这样做毫无价值好吧。。。
存那么多点的状态其实没必要我们只需存对于某个栅栏的两个端点即可。
经过贪心我们可以发现 对于第一个dp 我们的状态转移时这样的 :
f[i][0]=min(f[k][0]+abs(x[i]-x[k]),f[k][1]+abs(w[k]-x[i]));
f[i][1]=min(f[k][0]+abs(x[k]-w[i]),f[k][1]+abs(w[k]-w[i]));
其中 1<=k<i (还有一些限制没写看起来状态转移是错的)
对于当前i这个栅栏我们要走到其两端那么我只用看是否有一个决策前面已经覆盖了这个端点如果覆盖了这个端点那么这个决策之前的所有决策都是不合法的 因为他们不能直接以直线的形式过来这有当前决策可以以直线过来,因为没有其他的栅栏挡住了它。
我们完全可以开个数组来模拟这个过程 仔细思考贪心是正确的。且不具后效性。
但是这有转移仍是n^2 考虑优化 对于线段覆盖区间这种问题应该是有一种做法叫做浮水法能以很快的时间做出。
类似于 HAoi某一年的贴海报 当然这道题我是直接线段树的。
那么这个区间覆盖直接线段树即可。值得一提的是有坑点。
起点和输入和终点是否连到一块需注意这个坑了我好久。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
#define ll long long
#define l(x) t[x].l
#define r(x) t[x].r
#define add(x) t[x].add
#define k(x) t[x].k
#define z p<<1
#define y p<<1|1
#define max(x,y) (x>y?x:y)
#define min(x,y) (x>y?y:x)
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(ll x)
{
x<?putchar('-'),x=-x:;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=,maxn=;
int n,m;
int x[MAXN],w[MAXN];
ll f[MAXN][];//f[i][0/1]表示到达第i个栅栏的左边或者右边值最优
struct wy
{
int l,r;
int k;//决策
int add;
}t[(maxn<<)+];
void build(int p,int l,int r)
{
l(p)=l;r(p)=r;
if(l==r)return;
int mid=(l+r)>>;
build(z,l,mid);
build(y,mid+,r);
return;
}
void pushdown(int p)
{
add(y)=add(z)=add(p);
k(y)=k(z)=add(p);
add(p)=;return;
}
void change(int p,int l,int r,int v)
{
if(l<=l(p)&&r>=r(p))
{
add(p)=v;
k(p)=v;
return;
}
if(add(p))pushdown(p);
int mid=(l(p)+r(p))>>;
if(l<=mid)change(z,l,r,v);
if(r>mid)change(y,l,r,v);
return;
}
int ask(int p,int e)
{
if(l(p)==r(p))return k(p);
int mid=(l(p)+r(p))>>;
if(add(p))pushdown(p);
if(e<=mid)return ask(z,e);
else return ask(y,e);
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
memset(f,,sizeof(f));
for(int i=;i<=n;++i)
{
x[i]=read()+maxn;
w[i]=read()+maxn;
}
build(,,maxn<<);
f[][]=f[][]=;
x[]=maxn;w[]=maxn;
for(int i=;i<=n;++i)
{
int k1=ask(,x[i]);
int k2=ask(,w[i]);
f[i][]=min(f[k1][]+abs(x[i]-x[k1]),f[k1][]+abs(w[k1]-x[i]));
f[i][]=min(f[k2][]+abs(x[k2]-w[i]),f[k2][]+abs(w[k2]-w[i]));
change(,x[i],w[i],i);
}
put(min(f[n][]+abs(w[n]-m-maxn),f[n][]+abs(x[n]-m-maxn)));
return ;
}
dp很有意思
数据结构优化dp的更多相关文章
- HAOI2008 木棍分割 数据结构优化dp+二分答案
很久之前打的题,现在补篇博客 打滚动数组 #E. 木棍分割 Accepted 100 1712 ms 1512 KiB 2019-05-07 17:01:23 Short 不打滚动数组 #419. ...
- HDU 4990 Ordered Subsequence --数据结构优化DP
题意:给一串数字,问长度为m的严格上升子序列有多少个 解法:首先可以离散化为10000以内,再进行dp,令dp[i][j]为以第i个元素结尾的长度为j的上升子序列的个数, 则有dp[i][j] = S ...
- The Battle of Chibi(数据结构优化dp,树状数组)
The Battle of Chibi Cao Cao made up a big army and was going to invade the whole South China. Yu Zho ...
- Alternating Strings Gym - 100712D 简单dp && Alternating Strings II Gym - 100712L 数据结构优化dp
比赛链接:https://vjudge.net/contest/405905#problem/D 题意: 给你一个长度为n的由0或1构成的串s,你需要切割这个串,要求切割之后的每一个子串长度要小于等于 ...
- $Poj2376\ Poj3171\ Luogu4644\ Cleaning\ Shifts$ 数据结构优化$DP$
$Poj$ $AcWing$ $Luogu$ $ps:$洛谷题目与$Poj$略有不同,以下$Description$是$Poj$版.题目的不同之处在于洛谷中雇用奶牛的费用不相同,所以不可以 ...
- $HDOJ5542\ The\ Battle\ of\ Chibi$ 数据结构优化$DP$
$AcWing$ $Description$ $Sol$ 首先显然是是以严格递增子序列的长度为阶段,由于要单调递增,所以还要记录最后一位的数值 $F[i][j]$表示前$i$个数中以$A_i$结尾的长 ...
- 0x58 数据结构优化DP
补写一下 poj3171 设f[i]表示覆盖L~i的最小花费,把区间按左端点排序,枚举区间,f[a[i].r]=min{f[a[i].l~(a[top].r-1)]}+a[i].c (当然还要和原值比 ...
- 洛谷P4644 [USACO2005 Dec]Cleaning Shifts 清理牛棚 [DP,数据结构优化]
题目传送门 清理牛棚 题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness ...
- bzoj1233 单调队列优化dp
https://www.lydsy.com/JudgeOnline/problem.php?id=1233 数据结构优化dp的代码总是那么抽象 题意:奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Be ...
随机推荐
- Web从入门到放弃<7>
从这章开始读<javascript高级程序设计> <1>typeof 返回字符串 / 类型 未定义:undefined 布尔:boolean 字符串:string 数值:num ...
- css clip-path的polygon属性绘制多边形
通过设置多个点的坐标位置来绘制图形的形状 .box{ clip-path:polygon(x1 y1, x2 y2, x3 y3, , , , , ,) backgroud-color:red; }
- JVM 组成以及各部分作用
1.Java虚拟机的体系结构 2.jvm在系统中的布局 3.jvm装载一个类 当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class ...
- Leetcode | 组目录
数组 [1]999. 车的可用捕获量 [2]989. 数组形式的整数加法
- [转] Redux入门教程(快速上手)
学习前提 在我们开始以前,确保你熟悉以下知识: 函数式JavaScript 面向对象JavaScript JavaScript ES6 语法 同时,确保你的设备已经安装: NodeJS Yarn(或者 ...
- WIN10在安装mysql时,出现“The security settings could not be applied to the database because the connection has failed with the following error. Error Nr. 1045
解决方法:1, 首先卸载MySQL2, 再根据这个目录 C:\ProgramData,将MySQL删除.3, 重新安装MySQL 就好了(电脑不用重启)
- Django 学习第十一天——中间键和上下文处理器
一.中间键的引入: Django中间件(Middleware)是一个轻量级.底层的"插件"系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出. djang ...
- tar 压缩归档
压缩归档 掌握归档的定义:归档(archiving)就是将许多文件(或目录)打包成一个文件. 了解归档的目的:归档的目的就是方便备份.还原及文件的传输操作. 掌握tar命令的功能:将多个文件(也可能包 ...
- windows上react-native run-android时Exception in thread "main" java.lang.IllegalArgumentException: MALFORMED报错
报错如图 解决 在C:\Users\{用户名}\.gradle\wrapper\dists路径下,删除所有文件夹,重新run-android ps:网上搜了说是说是java解压缩编码格式问题什么的,感 ...
- angularjs 初始化方法执行两次以及url定义错误导致传值错误问题
1.初始化方法执行两次以上的问题定义一个 route.如下所示:.state('main.channelQryDetail', { url:'/channelDetail/:channelNo/:pa ...