【CodeForces】484E Sign on Fence

因为一个区间内的广告高度受限于最高的篱笆的高度,所以可以将所有的篱笆从高到低插入,成为一棵可持久化线段树。
维护区间内最长连续篱笆的长度
对每个询问,二分答案然后检查是否存在长度超过w的篱笆段

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define cint const int &

int tot,n,m,L,R,aim,w,root[N],l,r;

struct que{int h,i;friend bool operator < (que a,que b){return b.h<a.h;}}p[N];
struct node{int mx,l,r,lson,rson;bool tag;}t[N*25],ans;

inline void merge(node &a,node b,const node &c)
{
    a.tag=(b.tag&&c.tag);
    if (b.tag) a.l=b.l+c.l;else a.l=b.l;
    if (c.tag) a.r=b.r+c.r;else a.r=c.r;
    a.mx=max(max(max(b.mx,c.mx),max(a.l,a.r)),max(b.r+c.l,a.mx));
}

void insert(int &k,cint lk,cint l,cint r)
{
    if (!k) k=++tot;
    if (l==r){t[k].mx=t[k].l=t[k].r=t[k].tag=1;return;}
    int mid=l+r>>1;
    if (aim<=mid){insert(t[k].lson,t[lk].lson,l,mid);t[k].rson=t[lk].rson;}
    else {insert(t[k].rson,t[lk].rson,mid+1,r);t[k].lson=t[lk].lson;}
    merge(t[k],t[t[k].lson],t[t[k].rson]);
}

#define Lson t[k].lson,l,mid
#define Rson t[k].rson,mid+1,r

void build(int &k,cint l,cint r)
{
    k=++tot;
    if (l==r) return;
    int mid=l+r>>1;
    build(Lson);build(Rson);
}

void find(cint k,cint l,cint r)
{
    if (L<=l && r<=R) return merge(ans,ans,t[k]);
    int mid=l+r>>1;
    if (L<=mid) find(Lson);
    if (mid<R) find(Rson);
}

inline bool judge(cint k)
{
    ans=(node){0,0,0,0,0,0};
    find(root[k],1,n);
    return w<=ans.mx;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&p[i].h),p[i].i=i;
    sort(p+1,p+n+1);
    build(root[0],1,n);
    for (int i=1;i<=n;i++) aim=p[i].i,insert(root[i],root[i-1],1,n);
    scanf("%d",&m);
    while (m--)
    {
        scanf("%d%d%d",&L,&R,&w);
        l=1,r=n;
        for (int mid=l+r>>1;l<r;mid=l+r>>1) if (judge(mid)) r=mid;else l=mid+1;
        printf("%d\n",p[l].h);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值