一共考了两道题
一共水了70分(-_-||)【我还是太水了】
先说第二题,一道 区间更新,区间查询 的题目
上线段树,结果打了两百多行只有十分,别人n*n水了90分。。。
这题的难点是如何处理延迟标记
注意:在down中,左右儿子只对父亲传入的延迟标记进行更新
void down(int p) {
if(tree[p].q==-1&&tree[p].f==0)return;
if(tree[p].q!=-1){
tree[p<<1].f=0;
tree[p<<1|1].f=0;
tree[p<<1].q=tree[p].q;
tree[p<<1|1].q=tree[p].q;
if(tree[p].q==0)mem0(p<<1),mem0(p<<1|1);
else mem1(p<<1),mem1(p<<1|1);
tree[p].q=-1;
}
if(tree[p].f==1){
change(p<<1),change(p<<1|1);
tree[p<<1].f^=1;
tree[p<<1|1].f^=1;
}
tree[p].f=0;
}
第二题
题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。
通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。
另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。
在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?
输入 输入数据第一行包括3个整数,分别是T,MaxP,W。
接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。
输出 输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。
信息较多
但经分析可得状态转移方程(买):
dp[i][j]=max(dp[i][j],dp[ii][jj]-(j-jj)*ap[i])
//将ii天的jj张股票在第i天扩充成j张
分离参数(重点)得
dp[i][j]=dp[i-1][j]
dp[i][j]=max(dp[ii][jj]+jj*ap[i]){max(0,j-W-1)<jj<j}+j*ap[i]
由于在i j的循环中ii,jj,ap[i]都可预处理出来,
所以可以用线段树或单调队列完成查询
下面给出单调队列解法:
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define DOR(i,a,b) for(int i=(a);i>=(b);i--)
#define M 2005
using namespace std;
int ap[M],bp[M],as[M],bs[M];
int dp[M][M];
int Q1[M],Q2[M];
int D[M],D1[M];
inline int max(int x,int y){if(x>y)return x;return y;}
int main(){
int T,mx,W;
scanf("%d%d%d",&T,&mx,&W);
FOR(i,1,T)scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
memset(dp,-63,sizeof(dp));
FOR(i,1,W+1)FOR(j,0,mx){
if(j<=as[i])dp[i][j]=-j*ap[i];
if(i>1)dp[i][j]=max(dp[i][j],dp[i-1][j]);
}
FOR(i,W+2,T){
memset(Q1,0,sizeof(Q1));
memset(Q2,0,sizeof(Q2));
int ii=i-W-1;
FOR(j,0,mx){
D[j]=dp[ii][j]+j*bp[i];
D1[j]=dp[ii][j]+j*ap[i];
}
FOR(j,0,mx)dp[i][j]=max(dp[i][j],dp[i-1][j]);
int L=0,R=-1;
DOR(j,mx,0){
while(L<=R&&D[Q1[R]]<=D[j])R--;
Q1[++R]=j;
while(L<=R&&Q1[L]-j>bs[i])L++;
dp[i][j]=max(dp[i][j],D[Q1[L]]-j*bp[i]);
}
L=0,R=-1;
FOR(j,0,mx){
while(L<=R&&D1[Q2[R]]<=D1[j])R--;
Q2[++R]=j;
while(L<=R&&j-Q2[L]>as[i])L++;
dp[i][j]=max(dp[i][j],D1[Q2[L]]-j*ap[i]);
}
}
int ans=0;
FOR(i,0,mx)ans=max(ans,dp[T][i]);
printf("%d\n",ans);
return 0;
}