Luogu 2827/bzoj 4721(单调队列)

来源:互联网 发布:ubuntu安装中文输入法 编辑:程序博客网 时间:2024/06/07 23:08

传送门

题解:

如果x>y,显然x*p+q>(y+q)*p,所以:

如果优先选最长的切,那么次长蚯蚓的子段一定也在最长蚯蚓的子段之后,所以用三个单调递减队列维护长度(原长,前半截,后半截),每次选三个队首最大的那个,切成两段扔进后两个队列,此时队列一定仍满足单调性。

差不多就是个模拟题。。。

P.S.上bzoj交的要注意处理行末空格以及回车,但在洛谷必须保留。。。

Luogu 2827:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<climits>using namespace std;typedef long long ll;const int MAXN=7100004;struct Node {int v,t;friend bool operator <(const Node &a,const Node &b) {return a.v>b.v;}}q[3][MAXN];int h[3],t[3];int n,m,U,V,tt,add;inline int query(int id,int cur) {if (h[id]>t[id]) return -(INT_MAX-1);return q[id][h[id]].v+add*(cur-q[id][h[id]].t-1);}inline int qm(int cur) {int a=query(0,cur),b=query(1,cur),c=query(2,cur),mx=max(max(a,b),c);if (mx==a) return 0;if (mx==b) return 1;return 2;}inline int read() {int x=0;char c=getchar();while (c<'0'||c>'9') c=getchar();while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();return x;}int main() {//freopen("P2827.in","r",stdin);n=read(),m=read(),add=read(),U=read(),V=read(),tt=read();for (register int i=1;i<=n;++i) q[0][i].v=read();sort(q[0]+1,q[0]+n+1);h[0]=h[1]=h[2]=1,t[0]=n;for (register int i=1;i<=m;++i) {int id=qm(i),val=query(id,i);if (i%tt==0) printf("%d ",val);++h[id];q[1][++t[1]].v=(int)(1.0*U/V*val);q[2][++t[2]].v=val-(int)(1.0*U/V*val);q[1][t[1]].t=i;q[2][t[2]].t=i;}puts("");int nm=n+m;for (register int i=1;i<=nm;++i) {int id=qm(m+1);if (i%tt==0) printf("%d ",query(id,m+1));++h[id];}return 0;}


原创粉丝点击