CodeForces 627 B.Factory Repairs(BIT)

Description
一家工厂一天可以产出a件商品,但是设备需要维修,维修前每天只能产出b件商品,维修需要k天,这k天没有产出,修好后就可以恢复正常每天a件,现在给出一些订单的日期和数量以及一些查询,每次查询给出一个维修开始日期p表示第p天开始维修在n天内最多可以接多少单,注意订单只能当天完成
Input
第一行输入五个整数n,k,a,b,q表示总天数,维修需要天数,设备正常时每天的产出,设备未维修时每天的产出以及操作数,之后m行每行一种操作,1 d v表示有一个订单在第d天下了v个订单,2 p表示在第p天开始维修查询最多可以接多少订单
(1<=k<=n<=2e5,1<=b < a<=1e4,1<=q<=2e5,1<=v<=1e4,1<=p<=n-k+1)
Output
对于每次查询,输出查询结果
Sample Input
5 2 2 1 8
1 1 2
1 5 3
1 2 1
2 2
1 4 2
1 3 2
2 1
2 3
Sample Output
3
6
4
Solution
开两个BIT分别记录设备正常和不正常时第i天的订单数,如果某天的订单总数超过a,那么在第一个BIT中只更新到a,同理如果某天的订单总数超过b,那么在第二个BIT中只更新到b,对于一次维修p,1~p-1这段时间能够完成的订单总数为第二个BIT中1~p-1段的和,p+k~n这段时间能够完成的订单总数为第一个BIT中p+k~n段的和,每次修改和查询都是O(logn),总时间复杂度O(qlogn)
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 222222
int n,k,a,b,q,num[maxn];
struct BIT
{
    #define lowbit(x) (x&(-x))
    int b[maxn];
    void init()
    {
        memset(b,0,sizeof(b));
    }
    void update(int x,int v)
    {
        while(x<=n)
        {
            b[x]+=v;
            x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int ans=0;
        while(x)
        {
            ans+=b[x];
            x-=lowbit(x);
        }
        return ans;
    }
}x,y;
int main()
{
    while(~scanf("%d%d%d%d%d",&n,&k,&a,&b,&q))
    {
        memset(num,0,sizeof(num));
        x.init(),y.init();
        while(q--)
        {
            int op,d,v;
            scanf("%d%d",&op,&d);
            if(op==1)
            {
                scanf("%d",&v);
                if(num[d]+v<=b)x.update(d,v),y.update(d,v);
                else if(num[d]+v>b&&num[d]+v<=a)
                {
                    if(num[d]<b)x.update(d,b-num[d]);
                    y.update(d,v);
                }
                else if(num[d]+v>=a)
                {
                    if(num[d]<b)x.update(d,b-num[d]);
                    if(num[d]<a)y.update(d,a-num[d]);
                }
                num[d]+=v;
            }
            else
            {
                int ans=x.sum(d-1)-x.sum(0)+y.sum(n)-y.sum(d+k-1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值