CodeChef - WIQ Waiting in a Queue

CodeChef - WIQ Waiting in a Queue

数据结构

题意

一个队列里面有1到n,n个任务。每个任务有个准备时间,有个持续时间。从1时刻开始检查队列中的任务,遇到一个任务,如果他没准备好,那么把它移到队尾。如果他准备好了,那么做它,完事后就移除。

思路

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long LL;
const int MAXN=1000007;
const int oo=0x3f3f3f3f;
int sum[MAXN<<2];
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt)
{
    sum[rt]=0;
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int p, int c, int l, int r, int rt)
{
    if(l==r) { sum[rt]+=c; return; }
    int m=(l+r)>>1;
    if(p<=m) update(p, c, lson);
    else update(p, c, rson);
    pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
    if(L>R) return 0;
    if(L<=l&&r<=R) return sum[rt];
    int m=(l+r)>>1;
    int res=0;
    if(L<=m) res+=query(L, R, lson);
    if(m<R) res+=query(L, R, rson);
    return res;
}
struct People
{
    int i;
    LL a, b;
    LL res;
}peo[MAXN];
int ha[MAXN];
bool cmp1(People a, People b)
{
    if(a.b==b.b) return a.i<b.i;
    return a.b<b.b;
}
set<int> s;
int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("ou1.txt", "w", stdout);
    int T;scanf("%d", &T);
    while(T--)
    {
        int n;scanf("%d", &n);
        build(1, n, 1);
        for(int i=1;i<=n;i++)
        {
            peo[i].i=i;
            update(i, 1, 1, n, 1);
            scanf("%lld", &peo[i].a);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%lld", &peo[i].b);
            peo[i].b--;
        }
        sort(peo+1, peo+1+n, cmp1);
        for(int i=1;i<=n;i++)
        {
            ha[peo[i].i]=i;
        }
        LL cur_tim=0;s.clear();
        int ne=1;
        int exi=n;
        while(exi>0)
        {
            if(s.empty()&&ne<=n&&cur_tim+exi<=peo[ne].b) cur_tim+=(peo[ne].b-cur_tim)/exi*exi;
            while(ne<=n&&peo[ne].b<cur_tim+exi) s.insert(peo[ne++].i);
            set<int>::iterator it=s.begin();
            int la=0, now=0;
            while(it!=s.end())
            {
                now=(*it);
                cur_tim+=query(la+1, now, 1, n, 1);
                while(ne<=n&&peo[ne].b<cur_tim+exi) s.insert(peo[ne++].i);
                if(cur_tim>peo[ha[now]].b)
                {
                    update(now, -1, 1, n, 1);
                    cur_tim+=peo[ha[now]].a;
                    peo[ha[now]].res=cur_tim;
                    while(ne<=n&&peo[ne].b<cur_tim+exi) s.insert(peo[ne++].i);
                    exi--;
                    it++;
                    s.erase(now);
                }
                else
                {
                    it++;
                }
                la=now;
            }
            cur_tim+=query(now+1, n, 1, n, 1);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%lld%c", peo[ha[i]].res, i==n ? '\n' : ' ');
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值