列表

详情


NC229578. 无敌的强太郎

描述

阿强遇到了一群小混混。无敌的阿强打算用他的替身攻击消灭这些小混混。小混混站成了一排,一排的长度为n。他每秒钟会选择一段区间,消灭 个小混混。
如果小混混数量不足 k,则会消灭尽量多的小混混。
阿强作为一个拥有屎蛋的炮瓦的人,他选择的区间是不会相互包含的。他想要知道在之前每次都消灭尽量多的小混混的情况下,每秒最多能消灭的小混混的数量

输入描述

第一行为正整数n,含义见题意描述
接下来n行,每行一个整数a_i,表示第i个位置小混混的数量。
接下来一个整数m,含义见题意描述
接下来m行,每行三个整数l,r,k。l表示这一秒选择的区间的左端点,r表示右端点

保证数据随机

输出描述

为m行,每行输出一个整数,第i行输出的整数代表在之前每次都消灭尽量多的小混混的情况下,第i秒最多能消灭的小混混的数量

示例1

输入:

5
0 5 2 5 0 
3
2 4 2 
1 2 5 
3 5 8

输出:

2
5
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 263ms, 内存消耗: 10072K, 提交时间: 2021-11-17 23:48:46

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#define N 410000
using namespace std;
struct node{int l,r,h,id;}a[N];
struct node1{int l,r,lc,rc,lz,a,b,lza,lzb;}lt[2*N];
int s[N],tl,n,m,h[N],pos[N];
bool cmp(node x,node y)
{
    if(x.l<y.l) return 1;
    return 0;
}
void down(int now)
{
    int lc=lt[now].lc,rc=lt[now].rc;
    if(lt[now].lza)
    {
        lt[now].a+=lt[now].lza;
        if(lc) lt[lc].lza+=lt[now].lza;
        if(rc) lt[rc].lza+=lt[now].lza;
        lt[now].lza=0;
    }
    if(lt[now].lzb)
    {
        lt[now].b+=lt[now].lzb;
        if(lc) lt[lc].lzb+=lt[now].lzb;
        if(rc) lt[rc].lzb+=lt[now].lzb;
        lt[now].lzb=0;
    }
}
void upd(int now)
{
    int lc=lt[now].lc,rc=lt[now].rc;
    if(lc) down(lc);
    if(rc) down(rc);
    lt[now].a=min(lt[lc].a,lt[rc].a);
    lt[now].b=max(lt[lc].b,lt[rc].b);
}
void bt(int l,int r)
{
    int now=++tl;
    lt[now].l=l;lt[now].r=r;
    if(l<r)
    {
        int mid=(l+r)/2;
        lt[now].lc=tl+1;bt(l,mid);
        lt[now].rc=tl+1;bt(mid+1,r);
        upd(now);
    }
    else lt[now].a=s[a[l].r],lt[now].b=s[a[l].l-1];
}
int finda(int now,int l,int r)
{
    int lc=lt[now].lc,rc=lt[now].rc,mid=(lt[now].l+lt[now].r)/2;
    down(now);
    if(lt[now].l==l && lt[now].r==r) return lt[now].a;
    if(mid>=r) return finda(lc,l,r);
    else if(l>mid) return finda(rc,l,r);
    else return min(finda(lc,l,mid),finda(rc,mid+1,r));
}
int findb(int now,int l,int r)
{
    int lc=lt[now].lc,rc=lt[now].rc,mid=(lt[now].l+lt[now].r)/2;
    down(now);
    if(lt[now].l==l && lt[now].r==r) return lt[now].b;
    if(mid>=r) return findb(lc,l,r);
    else if(l>mid) return findb(rc,l,r);
    else return max(findb(lc,l,mid),findb(rc,mid+1,r));
}
void changea(int now,int l,int r,int d)
{
    int lc=lt[now].lc,rc=lt[now].rc,mid=(lt[now].l+lt[now].r)/2;
    down(now);
    if(lt[now].l==l && lt[now].r==r) {lt[now].lza+=d;return;}
    if(mid>=r) changea(lc,l,r,d);
    else if(l>mid) changea(rc,l,r,d);
    else changea(lc,l,mid,d),changea(rc,mid+1,r,d);
    upd(now);
}
void changeb(int now,int l,int r,int d)
{
    if(l>r) return;
    int lc=lt[now].lc,rc=lt[now].rc,mid=(lt[now].l+lt[now].r)/2;
    down(now);
    if(lt[now].l==l && lt[now].r==r) {lt[now].lzb+=d;return;}
    if(mid>=r) changeb(lc,l,r,d);
    else if(l>mid) changeb(rc,l,r,d);
    else changeb(lc,l,mid,d),changeb(rc,mid+1,r,d);
    upd(now);
}
void init()
{
    scanf("%d",&n);
    
    for(int i=1;i<=n;i++)
    {
        scanf("%d", &s[i]);
        s[i]+=s[i-1];
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].h),a[i].id=i;
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m;i++) pos[a[i].id]=i;
    bt(1,m);
}
void solve()
{
    for(int i=1;i<=m;i++)
    {
        int p=pos[i],A=finda(1,p,m),B=findb(1,1,p);
        int k=min(A-B,a[p].h);
        printf("%d\n",k);
        changea(1,p,m,-k);
        changeb(1,p+1,m,-k);
    }
}
int main()
{
    init();
    solve();
    return 0;
}

上一题