AcWing 133 蚯蚓(队列)

AcWing 133 蚯蚓

链接

image-20210726204249044

1.我们先把原序列排序,因为不管怎么切,先被切的蚯蚓分成的两部分一定比后切的蚯蚓分成的两部分大(较大的部分和较大的部分比较,较小的部分和较小的部分比较),所以我们可以省去每一秒增加每只蚯蚓的长度这个操作,转换成在查询砍那只蚯蚓时,把增加的长度算到蚯蚓的总长度上。(具体证明方法可以查看《算法进阶指南》)

2.我们可以维护三个队列,方便存原长度和切完两部分的长度,队列元素从大到小。

3.寻找每次砍哪一只蚯蚓就是在队列1、队列2、队列3的队头找一个算上增加的长度最大的蚯蚓,之后把他出队,切开的两部分分别进入队2、队3。

#include<iostream>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<list>
#define mem(a,n) memset(a,n,sizeof a)
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define SYS system("pause");
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;

ll gcd(ll a,ll b){ll d; while(b){ d=b; b=a%b; a=d; } return a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll qpow(ll x, ll y) { ll ans = 1; for (; y > 0; y >>= 1) { if (y & 1)ans *= x; x *= x; } return ans;}
ll qpow(ll x, ll y, int MOD) { ll ans = 1; for (; y > 0; y >>= 1) { if (y & 1)ans = ans*x%MOD; x = x*x%MOD; } return ans;}
void exgcd(int a,int b,int &x,int &y){ if(b==0){ x=1;y=0;return; } exgcd(b,a%b,x,y); int temp=y; y=x-(a/b)*y, x=temp; return;}
int downcheck(int l, int r){ while (l < r){ int mid = l + r >> 1; if ("check(mid)") r = mid; else l = mid + 1; } return l;}
int upcheck(int l, int r){ while (l < r){ int mid = l + r + 1 >> 1; if ("check(mid)") l = mid; else r = mid - 1;} return l;}
int doublecheck(int l,int r){ while(r-l>1e-8){ int mid=(l+r)>>1; if("check(mid)") l=mid; else r=mid;} return l; }

const int N = 4e5+10,M=20;
const int inf=0x3f3f3f3f;
const int mod=1e9+7; 
const double pi = acos(-1.0);
int a[N];
ll n, m, q, p, u, v,t;
ll temp1, temp2;
queue<ll> q1, q2, q3;
int calc(ll t){
    ll x=-1,a=-1,b=-1,c=-1;
    if (!q1.empty())  a=q1.front()+t*q;
    if (!q2.empty())  b=q2.front()+t*q;
    if (!q3.empty())  c=q3.front()+t*q;
    x=max(a,max(b,c));
    if (x==a)q1.pop();
    else if (x==b)q2.pop();
    else if(x==c) q3.pop();
    return x;
}
int main(){
    IOS
    cin >> n >> m >> q >> u >> v >> t;
    p = u / v;
    for (int i = 1; i <= n;i++){
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    for (int i = n; i >= 1;i--){
        q1.push(a[i]);
    }
    for (int i = 1; i <= m;i++){
        ll res = calc(i - 1);
        if(!(i%t)){
            cout << res << ' ';
        }
        temp1 = floor(res * p), temp2 = res - temp1;
        q2.push(temp1 - i * q), q3.push(temp2 - i * q);
        cout << endl;
        for (int i = 1; i <= n + m;i++){
            res = calc(m);
            if(!(i%t))cout<<res<<' ';
        }
    }
        return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值