Codeforces Round 974 (Div. 3)D题解析

前三道太水了,第三道一眼二分,就是需要注意要超过一半人就行,我因为检查了好久

D. Robert Hood and Mrs Hood

 

抱歉,我是蒟蒻,我看到区间问题就想到了线段树,我们只需要用线段树去维护每个点药经历多少任务即可

我们用线段树去维护,每个点会覆盖几个任务点即可,我们一个任务,假设开始时间为L,结束时间为R ,因此我们什么时候来能够赶上这个任务呢?很明显是从L-d+1~R这个时间来都能碰到这个任务,因此,我们就需要给这个区间+1

然后最后去查每个点的权值即可,时间复杂度为O(logn)

#include<bits/stdc++.h>  
using namespace std;  
#define int long long
int t;  
int n,d,k;  
int l,r;  
struct node  
{  
    int l;  
    int r;  
    long long sum; 
    long long lz;  
}tree[1000006*4];  

void push_down(int i)  
{  
    if(tree[i].lz != 0)  
    {  
        tree[i*2].lz += tree[i].lz;  
        tree[i*2].sum += tree[i].lz * (tree[i*2].r - tree[i*2].l + 1);  
        tree[i*2+1].lz += tree[i].lz;  
        tree[i*2+1].sum += tree[i].lz * (tree[i*2+1].r - tree[i*2+1].l + 1); 
        tree[i].lz = 0; 
    }   
}  

void build(int i,int l,int r)  
{  
    tree[i].lz = 0;  
    tree[i].l = l;  
    tree[i].r = r;  
    
    if(l == r)  
    {  
        tree[i].sum = 0; 
        return;  
    }  
    
    int mid = (l + r) / 2;  
    build(i*2, l, mid);  
    build(i*2+1, mid + 1, r);  
    tree[i].sum = tree[i*2].sum + tree[i*2+1].sum; 
}  

void add(int i,int l,int r,int k)  
{  
    if(l <= tree[i].l && tree[i].r <= r)  
    {  
        tree[i].sum += k * (tree[i].r - tree[i].l + 1);  
        tree[i].lz += k;
        return;  
    }  
    
    push_down(i);  
    int mid = (tree[i].l + tree[i].r) / 2;  
    
    if(l <= mid)  
        add(i*2, l, r, k);  
    if(r > mid)  
        add(i*2+1, l, r, k);  
    
    tree[i].sum = tree[i*2].sum + tree[i*2+1].sum; 
}  

long long find(int i,int l,int r)  
{  
    if(tree[i].l >= l && tree[i].r <= r)  
    {  
        return tree[i].sum;  
    }  

    push_down(i);  
    long long ans = 0;  
    int mid = (tree[i].l + tree[i].r) / 2;  
    
    if(l <= mid)  
        ans += find(i*2, l, r);  
    if(r > mid)  
        ans += find(i*2+1, l, r);  
    
    return ans;  
}  

void solve()  
{  
    cin >> n >> d >> k;  
    build(1, 1, n);  
    
    for(int i = 1; i <= k; i++)  
    {  
        cin >> l >> r;  
        add(1, max(1, l-d+1), r, 1);  
    }  
    
    int minn = 1, maxn = 1;  
    long long minnz = find(1, 1, 1);   
    long long maxnz = find(1, 1, 1);  
    
    for(int i = 1; i <= n - d + 1; i++)  
    {  
        long long cnt = find(1, i, i);  
        if(cnt < minnz)  
        {  
            minnz = cnt;  
            minn = i;  
        }  
        else if(cnt > maxnz)  
        {  
            maxnz = cnt;  
            maxn = i;  
        }  
    }  
    
    cout << maxn << " " << minn << '\n';  
}  

signed main()  
{  
    ios_base::sync_with_stdio(0);  
    cin.tie(0);  
    cout.tie(0);  
    
    cin >> t;  
    while(t--)  
    {  
        solve();  
    }  
    return 0;  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值