https://vjudge.net/contest/50935#problem/J
师兄的代码好看,就照这个模板吧
int stk[N];
int a[N],L[N],R[N];
LL sum[N];
int main(){
int n;
while(~sf("%d",&n)){
sum[0]=0;
rep(i,1,n){sf("%d",&a[i]),sum[i]=sum[i-1]+a[i];}
int top=0;
a[0]=-1;a[n+1]=-1;
rep(i,0,n+1){
while(top&&a[i]<=a[stk[top-1]])
--top,R[stk[top]]=i-1;
if(top)
L[i]=stk[top-1]+1;
stk[top++]=i;
}
LL ans=0;int id=0;
rep(i,1,n){
if(ans<=(sum[R[i]]-sum[L[i]-1])*a[i]){
ans=(sum[R[i]]-sum[L[i]-1])*a[i];
id=i;
}
}
cout<<ans<<endl;
pf("%d %d\n",L[id],R[id]);
}
}
https://vjudge.net/contest/50935#problem/K
哇,居然自己过了。。还是模仿师兄的好
int stk[N],a[N],R[N],L[N];
int main(){
//freopen("in.txt","r",stdin);
int n;
while(~sf("%d",&n)){
int top=0;
rep(i,1,n){sf("%d",&a[i]); L[i]=i+1;}
a[n+1]=inf;
rep(i,1,n+1){
while(top&&a[i]>=a[stk[top-1]])
--top,R[stk[top]]=i-1;
stk[top++]=i;
}
LL ans=0;
rep(i,1,n){
ans+=(R[i]-L[i]+1);
}
cout<<ans<<'\n';
}
}
https://vjudge.net/contest/50935#problem/L
终于做了一道 单调队列+ dp 的题目了,师兄的代码还是那么好看。。
int n,m;
int dp[120][mxn];
struct node{
int val,p;
bool friend operator<(node a,node b){
return a.val<b.val;
}
node(int val,int p):val(val),p(p){};
};
struct worker{
int l,p,s;
bool friend operator<(worker a,worker b){
return a.s<b.s;
}
}a[150];
int l[N],p[N],s[N];
int main(){
//freopen("in.txt","r",stdin);
while(~sf("%d%d",&n,&m)){
mem(dp,0);
rep(i,1,m){ sf("%d%d%d",&a[i].l,&a[i].p,&a[i].s); }
sort(a+1,a+1+m);
rep(i,1,m){ l[i]=a[i].l;p[i]=a[i].p,s[i]=a[i].s; }
for(int i=1;i<=m;++i){
priority_queue<node>q;
for(int k=0;k<s[i];++k){
q.push(node(dp[i-1][k]-k*p[i],k));
}
for(int j=1;j<=n;++j){
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(j>=s[i]&&j<s[i]+l[i]){
while((j-q.top().p)>l[i]){
q.pop();
// if(q.empty())puts("e");
}
dp[i][j]=max(dp[i][j],j*p[i]+q.top().val);
}
}
}
pf("%d\n",dp[m][n]);
}
}
不过这个代码不像是的用单调队列的,,
贴个别人的,用单调队列的。。
https://github.com/zhu8655/OI_Solution/blob/master/POJ_1821.cpp
https://vjudge.net/problem/ZOJ-3699
这个地方师兄用的双端队列很好,思想也很好。
然而找不到为何Segmentation Fault。。。
int price[N],cost[N];
struct gas{
int vol,pri;
gas(int vol,int pri):vol(vol),pri(pri){};
};
int main(){
int T;sf("%d",&T);
while(T--){
int n,cap;sf("%d%d",&n,&cap);
int flag=0;
rep(i,1,n){
int a,b;sf("%d%d%d",&a,&b,&price[i]);
if(a*b>cap)flag=1;
cost[i]=a*b;
}
if(flag){puts("Impossible");continue;}
LL ans=0;
deque<gas>dq;
int vol=0;
for(int i=1;i<=n;++i){
while(!dq.empty()&&price[i]>dq.back().pri){
vol-=dq.back().vol;
dq.pop_back();
}
dq.push_back(gas(cap-vol,price[i]));
int need=cost[i];
while(need){
gas& cur=dq.front();
int Min=min(cur.vol,need);
cur.vol-=Min;
need-=Min;ans+=1LL*cur.pri*Min;
if(!cur.vol)dq.pop_front();
}
}
cout<<ans<<'\n';
}
}
然后有点不懂了,只能再去看别人的代码。。、http://blog.csdn.net/acvay/article/details/46798685这个的代码还挺好的。。
单调队列+ dp
dp[i][j]表示第 i 天,有 j 股的最大收益
状态转移 dp[i][j]=max{dp[i-1]j,dp[r][k]-(j-k)*pa[i](i-r>w,j-k<=na[i],买),dp[r][k]+(k-j)*pb[i](i-r>w,k-j<=nb[i],卖)}
复杂度 为 t*t*p*p
首先我们可以看出 dp[i][j]>=dp[i-1][j](不买不卖转移)
所以可以将 r 确定为 i-w-1,复杂度变为t*p*p 还是很大
然后对于买,移项有
dp[i][j]+j*pa[i]=dp[r][k]+k*pa[i]。右边与 j无关, 可见我们只需要对每一个 i 维护一个关于k的单调队列,就可以在 p时间内求出所有的dp[i][j]
师兄的代码有点不同。。https://vjudge.net/solution/2611950
2:45到4:45
花了快两个小时做一个atcoder 只做了3题。。 结果题目都是看别人的。。。
题解
https://acmle.com/d/70-atcoder-regular-contest-075
醉了,都不会,,只能看
这个
其中E提还是看了这个,而且还有回顾用”树状数组求逆序对“。。。(看来太水了)
http://www.cnblogs.com/yxg123123/p/6938882.html
PS:数组要从0开始算,不然会少算长度为1的连续子序列。
(debug了很久这个。。。)
晚上就回顾了以前做的题,有些还是不会。。。