2016 UESTC Training for Dynamic Programming
强行做做试试看吧。
http://acm.hust.edu.cn/vjudge/contest/124721#overview
密码:mytrain
C - 柱爷与咸鱼神功
一个简单01背包。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
int v[];
int t[];
int p[];
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
int n,m;
cin>>m>>n;
for(int i=;i<n;i++)
{
scanf("%d%d",&t[i],&p[i]);
}
for(int i=;i<n;i++)
{
for(int j=m;j>=t[i];j--)
{
v[j]=max(v[j],v[j-t[i]]+p[i]);
}
}
cout<<v[m]<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
E - 柱爷与最大区间和
题意从一个区间中选取两个不相邻的区间使得这两个区间和最大.
dp[i][j]表示前j个数分成i份时且选择最后一个数的最大和,dp[i][j]=max(dp[i][j-1]+num[j],dp[i-1][k]+num[j]) (0<k<j-1)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
int dp[][];
int pre[];
int num[];
int main()
{
#ifdef local
freopen("in","r",stdin);
// freopen("out","w",stdout);
int _time=clock();
#endif
int n;
cin>>n;
for(int i=;i<=n;i++)
{
sd(num[i]);
pre[i-]=-inf;
}
dp[][]=-inf;
for(int i=;i<=n;i++)
{
dp[][i]=max(dp[][i-]+num[i],num[i]);
}
pre[]=dp[][];
for(int i=;i<=n;i++)
{
pre[i]=max(pre[i-],dp[][i]);
}
dp[][]=-inf;
for(int j=;j<=n;j++)
{
dp[][j]=max(dp[][j-],pre[j-])+num[j];
}
int ans=-inf;
for(int i=;i<=n;i++)
ans=max(dp[][i],ans);
cout<<ans<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
Q - 柱爷的下凡
01背包,打表预处理一下,肯定第一个硬币是1的,枚举另两个
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
int ans1[],ans2[];
void init()
{
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
ans1[]=,ans2[]=;
}
/*
int num[4]={0,1};
int dp[205];
void biao()
{
for(int n=4;n<=200;n++)
{
int b,c;
int cnt=inf;
for(num[2]=2;num[2]<n;num[2]++)
{
for(num[3]=num[2]+1;num[3]<=n;num[3]++)
{
memset(dp,127/3,sizeof dp);
dp[0]=0;
for(int i=1;i<=3;i++)
{
for(int j=num[i];j<=n;j++)
{
dp[j]=min(dp[j-num[i]]+1,dp[j]);
}
}
for(int i=1;i<=n;i++)
dp[i]+=dp[i-1];
if(dp[n]<cnt)
{
b=num[2],c=num[3];
cnt=dp[n];
}
}
}
printf("ans1[%d]=%d,ans2[%d]=%d;\n",n,b,n,c);
}
}*/
int main()
{
#ifdef local
freopen("in","r",stdin);
// freopen("out","w",stdout);
int _time=clock();
#endif
// biao();
init();
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
printf("%d %d %d\n",,ans1[n],ans2[n]);
}
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
B - 柱爷大战滑稽王
求LCS,但是数据n是1e6,特殊的是Ai每个数都不同,我们可以把LCS转LIS,记录Ai在Bi的位置作为一个序列,然后求出这个序列的LIS就是LCS了,这个网上有挺多的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
map<int,int>mp;
int x[];
int d[];
int lis(int n)
{
if(!n)return ;
int ans=;
d[]=x[];
for(int i=;i<n;i++){
if(x[i]>d[ans])d[++ans]=x[i];
else{
int pos=lower_bound(d,d+ans+,x[i])-d;
d[pos]=x[i];
}
}
return ans+;
}
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
int n,m,c;
int a;
mp.clear();
cin>>n>>m;
for(int i=;i<=n;i++){
sd(a);
mp[a]=i;
}
n=;
for(int i=;i<m;i++){
sd(a);
c=mp[a];
if(c){
x[n++]=c;
}
}
cout<<lis(n)+<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
N - 柱爷抢银行II
一个环,在环中连续取至多k个数,使得取的数和最大
记sum[i]为前i项和,dp[i]为以i结尾时,dp[i]-i这段范围取得和最大,所以dp[i]=x(i-k<x<i,且max(sum[i]-sum[x])).
单调队列维护sum[i]递减就行
代码写的很渣。。感觉这题有点奇怪题目说了如果想等的话就选区间最小的
3 2
0 0 3
。这种数据,我开始的代码是显示3 3 3一直wa,改了单调队列一点之后变成3 2 3然后居然AC了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
LL sum[];
LL dp[];
LL x[];
int q[];
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
LL c;
int l,r;
int n,k;
cin>>n>>k;
for(int i=;i<=n;i++){
cin>>x[i];
sum[i]=sum[i-]+x[i];
}
for(int i=n+;i<=*n;i++){
sum[i]=sum[i-]+x[i-n];
}
q[]=;
int head=,tail=;
for(int i=;i<=*n;i++)
{
while(head<=tail&&i-q[head]>k)head++;
dp[i]=q[head];
while(sum[i]<sum[q[tail]]&&tail>=head)tail--;
q[++tail]=i;
}
int t=;
for(int i=;i<=*n;i++)
{
if(sum[i]-sum[dp[i]]>sum[t]-sum[dp[t]])
{
t=i;
}
else if(sum[i]-sum[dp[i]]==sum[t]-sum[dp[t]]&&(i-dp[i]<t-dp[t]||(dp[t]+)-((dp[t]+)>n?n:)>(dp[i]+)-((dp[i]+)>n?n:)))
{
t=i;
}
}
c=sum[t]-sum[dp[t]];
r=t-(t>n?n:);
l=(dp[t]+)-((dp[t]+)>n?n:);
cout<<c;
printf(" %d %d\n",l,r);
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
L - 柱爷的矩阵
假如要选i,j,如果b[i]>b[j],那我们肯定先选b[i],所以先按b[i]降序排序
dp[i][j]表示选取第i列第j行时的最大值,
dp[i][j]=max(dp[i-1][k])(k<j)+max(a[j]-b[j]*(i-1),0);
dp[i-1][k]这个东西我们可以用多个二维数组来维护pre[i][j]=max(dp[i][j-1],dp[i][j]);
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const LL mod=;
struct node
{
int a,b;
}mp[];
bool cmp(node a,node b)
{
return a.b>b.b;
}
int dp[][];
int p[][];
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
int n,m;
cin>>n>>m;
for(int i=;i<n;i++)
{
cin>>mp[i].a;
}
for(int i=;i<n;i++)
{
cin>>mp[i].b;
}
sort(mp,mp+n,cmp);
int ans=;
for(int i=;i<=m;i++)
{
for(int j=;j<n;j++)
{
dp[i][j]=p[i-][j-]+max(mp[j].a-mp[j].b*(i-),);
p[i][j]=max(p[i][j-],dp[i][j]);
ans=max(p[i][j],ans);
}
}
cout<<ans<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
I - 柱爷与子序列
这题和FZU有一题很像。树状数组好题。
dp[i]=sum(dp[A[i]]-k],dp[A[i]]+k])+1.
这样答案算是算不考虑m>=2的。所以我们最后需要减去n;
每次查询(A[i]-k,A[i]+k)区间和=sum,然后再在add(A[i],sum+1),最后read(最远点)-n.数据太大,需要离散化一下。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
#define maxn 1000005
const int inf=0x3f3f3f3f;
const int mod=;
int nn;
int tree[];
int a[],b[];
void add(int d,int x)
{
while(d<=nn)
{
tree[d]=(tree[d]+x)%mod;
d+=(d&-d);
}
}
int read(int x)
{
int sum=;
while(x)
{
sum=(sum+tree[x])%mod;
x-=(x&-x);
}
return sum;
}
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
int n,k;
cin>>n>>k;
for(int i=;i<n;i++)
{
sd(a[i]);
b[i]=a[i];
}
sort(a,a+n);
nn=unique(a,a+n)-a;
int z,l,r;
for(int i=;i<n;i++)
{
z=lower_bound(a,a+nn,b[i])-a+;
l=lower_bound(a,a+nn,b[i]-k)-a+;
r=upper_bound(a,a+nn,b[i]+k)-a;
int sum=(read(r)-read(l-)+mod)%mod;
add(z,sum+);
}
cout<<(read(nn)-n+mod)%mod<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
G - 柱爷与三叉戟不得不说的故事
15种元素,状压DP搞一下1<<15种状态,
dp[i]=min(dp[i],dp[j]+dp[i^j]);
开始全部初始化为最大值,然后根据条件保留各个状态的最小值最后答案是dp[1<<15-1];
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
const int inf=0x3f3f3f3f;
const int mod=;
const int maxn=(<<)+;
int dp[maxn];
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
memset(dp,/,sizeof dp);
int d,a;
for(int i=;i<;i++)
cin>>d,dp[<<i]=d;
int n;
cin>>n;
for(int i=;i<n;i++)
{
int m;
sd(m);
int sta=;
for(int j=;j<m;j++)
{
sd(a);
sta+=(<<(a-));
}
cin>>d;
dp[sta]=min(dp[sta],d);
}
int last=(<<)-;
for(int i=;i<=last;i++)
{
for(int j=i;j;j=(j-)&i)
{
dp[i]=min(dp[i],dp[j]+dp[j^i]);
}
}
cout<<dp[last]<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
A - 柱爷的恋爱
区间dp
dp[i][j]表示[i,j)的所有合法方案
dp[i][i]=1;
然后我们记忆化递归
dfs(i,j)
假设我们不删i的话我们就需要找出和i对应的括号来算
res+=dfs(i+1,a)*dfs(a+1,j);算出每一个a.
如果删去i就是直接res+=dfs(i+1,j);
最后减1,因为答案不允许删掉所有东西。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
const int inf=0x3f3f3f3f;
const int mod=;
const int maxn=+;
LL dp[maxn][maxn];
char s[maxn];
LL dfs(int l,int r)
{
int ans=;
if(dp[l][r]!=-)return dp[l][r];
if(l==r)
ans=;
else
{
dp[l][r]=;
char fi='\0';
if(s[l]=='(')fi=')';
if(s[l]=='[')fi=']';
if(fi!='\0')
{
for(int i=l+; i<r; i++)
{
if(s[i]==fi)
{
ans=(ans+dfs(l+,i)*dfs(i+,r))%mod;
}
}
}
ans=(ans+dfs(l+,r))%mod;
}
dp[l][r]=ans;
return ans;
}
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
for(int i=; i<maxn; i++)for(int j=; j<maxn; j++)dp[i][j]=-;
int n;
cin>>n;
cin>>s;
cout<<(dfs(,n)+mod-)%mod<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
M - 柱爷的宝藏
普通转移就是,记dp[i]为以i结尾的最大值
dp[i]=max(dp[j]+(sum[i]-sum[j])^2+m);
n^2肯定TLE。然后就学到一个奇妙的斜率优化。。(http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <stack>
#include <vector>
#include <set>
using namespace std; typedef long long LL;
typedef unsigned long long uLL;
typedef double db;
#define X first
#define Y second
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define sd(x) scanf("%d",&(x))
#define Pi acos(-1.0)
#define sf(x) scanf("%lf",&(x))//GL&HF
#define ss(x) scanf("%s",(x))
const int inf=0x3f3f3f3f;
const int mod=;
const int maxn=+;
LL dp[];
LL sum[];
LL m;
int q[];
int n;
LL getdp(int i,int j)
{
return dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+m;
}
LL dp_up(int i,int j)
{
return dp[i]+sum[i]*sum[i]-(dp[j]+sum[j]*sum[j]);
}
LL dp_down(int i,int j)
{
return 1LL**(sum[i]-sum[j]);
}
int main()
{
#ifdef local
freopen("in","r",stdin);
//freopen("out","w",stdout);
int _time=clock();
#endif
cin>>n>>m;
for(int i=;i<=n;i++)
cin>>sum[i],sum[i]+=sum[i-];
dp[]=;
int head=,tail=;
q[tail++]=;
for(int i=;i<=n;i++)
{
while(head+<tail&&dp_up(q[head+],q[head])<=sum[i]*dp_down(q[head+],q[head]))head++;
dp[i]=getdp(i,q[head]);
while(head+<tail&&dp_up(i,q[tail-])*dp_down(q[tail-],q[tail-])<=dp_up(q[tail-],q[tail-])*dp_down(i,q[tail-]))tail--;
q[tail++]=i;
}
cout<<dp[n]<<endl;
#ifdef local
printf("time: %d\n",int(clock()-_time));
#endif
}
还有几题有点打算弃坑。。
2016 UESTC Training for Dynamic Programming的更多相关文章
- UESTC_酱神寻宝 2015 UESTC Training for Dynamic Programming<Problem O>
O - 酱神寻宝 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_导弹拦截 2015 UESTC Training for Dynamic Programming<Problem N>
N - 导弹拦截 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_酱神的旅行 2015 UESTC Training for Dynamic Programming<Problem M>
M - 酱神的旅行 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_菲波拉契数制升级版 2015 UESTC Training for Dynamic Programming<Problem L>
L - 菲波拉契数制升级版 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Su ...
- UESTC_摩天轮 2015 UESTC Training for Dynamic Programming<Problem K>
K - 摩天轮 Time Limit: 10000/4000MS (Java/Others) Memory Limit: 262143/262143KB (Java/Others) Submi ...
- UESTC_男神的约会 2015 UESTC Training for Dynamic Programming<Problem J>
J - 男神的约会 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- UESTC_邱老师选妹子(二) 2015 UESTC Training for Dynamic Programming<Problem I>
I - 邱老师选妹子(二) Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Su ...
- UESTC_邱老师选妹子 2015 UESTC Training for Dynamic Programming<Problem H>
H - 邱老师选妹子 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
- UESTC_邱老师玩游戏 2015 UESTC Training for Dynamic Programming<Problem G>
G - 邱老师玩游戏 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
随机推荐
- c#控制台实现post网站登录
如题,首先我写了一个web页面来实现post登陆,只做演示,代码如下 public void ProcessRequest(HttpContext context) { context.Respons ...
- JavaScript 函数的定义-调用、注意事项
函数定义 函数语句定义 function(a,b){ return a+b; } 表达式定义 var add = function(a,b){return a+b}; //函数表达式可以包含名称,这在 ...
- 装饰器模式(Decorator)——深入理解与实战应用
本文为原创博文,转载请注明出处,侵权必究! 1.初识装饰器模式 装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能.其结构图如下: Component为统一接口,也是装饰类和被装 ...
- linux下如何查看mysql、apache是否安装,并卸载
--linux下如何查看mysql.apache是否安装,并卸载? http://blog.163.com/dengxiuhua126@126/blog/static/1186077720137311 ...
- 深入tornado中的IOStream
IOStream对tornado的高效起了很大的作用,他封装了socket的非阻塞IO的读写操作.大体上可以这么说,当连接建立后,服务端与客户端的请求响应都是基于IOStream的,也就是说:IOSt ...
- 读书笔记 effective c++ Item 50 了解何时替换new和delete 是有意义的
1. 自定义new和delete的三个常见原因 我们先回顾一下基本原理.为什么人们一开始就想去替换编译器提供的operator new和operator delete版本?有三个最常见的原因: 为了检 ...
- Latex 公式在线可视化编辑器
寻觅 最近的一个demo需要用到Latex公式在线编辑器,从搜索引擎一般会得到类似http://latex.codecogs.com/eqneditor/editor.php的结果,这个编辑器的问题在 ...
- 【算法】RMQ LCA 讲课杂记
4月4日,应学弟要求去了次学校给小同学们讲了一堂课,其实讲的挺内容挺杂的,但是目的是引出LCA算法. 现在整理一下当天讲课的主要内容: 开始并没有直接引出LCA问题,而是讲了RMQ(Range Min ...
- Java--定时器问题
定时器问题 定时器属于基本的基础组件,不管是用户空间的程序开发,还是内核空间的程序开发,很多时候都需要有定时器作为基础组件的支持.一个定时器的实现需要具备以下四种基本行为:添加定时器.取消定时器.定时 ...
- JDK与Apache Tomcat服务器的安装步骤
先解释一下JDK和Tomcat是什么: Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP ...