玲珑oj 1129

链接
一道经典的线段树的题 , 注意下 query 的处理就好了 , 用到了 lazy , 算是自己复习了一遍线段树。

#include <bits/stdc++.h>
#define sc scanf
#define pr printf
const int N = 100010;
using namespace std;
long long tree[N<<2],lazy[N<<2];

void printf_tree(int root , int l , int r);
void Lazy(int root);
void Create_tree(int root , int l , int r);
void update(int root , int l , int r , int lh , int rh , long long value);
long long query(int root , int l , int r , int lh , int rh , long long value);
int main(int argc, char *argv[])
{
    int t , n , q , i , j;
    int opt , l , r;
    long long value;
    sc("%d",&t);
    while (t--)
    {
        sc("%d %d",&n , &q);
        memset(tree,0,sizeof(tree));
        memset(lazy,0,sizeof(lazy));
        Create_tree(1,1,n);

        while(q--)
        {
            sc("%d %d %d %lld",&opt , &l , &r , &value);
            if(opt == 1)
            {
                long long ans = query(1,1,n,l,r,value);
                pr("%lld\n",ans);
            }
            else
            {
                update(1,1,n,l,r,value);
               // query(1,1,n,l,r,value);
            }
           // printf_tree(1,1,n);
            //pr("\n\n");
        }
    }
    return 0;
}
void Create_tree(int root , int l , int r)
{
    if(l == r)
    {
        sc("%lld",&tree[root]); return ;
    }
    int mid = (l+r)>>1;
    Create_tree(root*2,l,mid);
    Create_tree(root*2+1,mid+1,r);

    tree[root] = max(tree[root*2] , tree[root*2+1]);
    return ;
}
void update(int root , int l , int r , int lh , int rh , long long value)
{
    //pr("%d %d %d %d %lld %lld\n",l,r,lh,rh,tree[root*2],tree[root*2+1]);
    if(l == lh && r == rh)
    {
        tree[root] += value;
        lazy[root] += value;
        return ;
    }
    int mid = (l+r)>>1;
    if(mid < lh)
        update(root*2+1,mid+1,r,lh,rh,value);
    else if(mid >= rh)
        update(root*2,l,mid,lh,rh,value);
    else
    {
        update(root*2,l,mid,lh,mid,value);
        update(root*2+1,mid+1,r,mid+1,rh,value);
    }
    tree[root] = max(tree[root*2] , tree[root*2+1]);
}
long long query(int root , int l , int r , int lh , int rh , long long value)
{

    if(l == r)
    {
        if(tree[root]>=value)  return l;
        return -1;
    }
    Lazy(root);
    tree[root] = max(tree[root*2],tree[root*2+1]);

    int mid = (l+r)>>1;
    if(lh<=l && r<=rh)
    {
        if(tree[root*2] >= value)
            return query(root*2,l,mid,lh,rh,value);
        else if(tree[root*2+1] >= value)
            return query(root*2+1,mid+1,r,lh,rh,value);
        return -1;
    }
    long long idx;
    if(mid < lh)
        return query(root*2+1,mid+1,r,lh,rh,value);
    else if(mid >= rh)
        return query(root*2,l,mid,lh,rh,value);
    else
    {
        idx = query(root*2,l,mid,lh,mid,value);
        if(idx != -1)
            return idx;
        idx = query(root*2+1,mid+1,r,mid+1,rh,value);
        if(idx != -1)
            return idx;
    }
   return -1;
}

void Lazy(int root)
{
    if(lazy[root])
    {
        lazy[root*2] += lazy[root];
        lazy[root*2+1] += lazy[root];

        tree[root*2] += lazy[root];
        tree[root*2+1] += lazy[root];

        lazy[root] = 0;
    }
}
void printf_tree(int root , int l , int r)
{
    if(l == r)
    {
        pr("%lld ",tree[root]); return ;
    }
    int mid = (l+r)>>1;
    printf_tree(root*2,l,mid);
    printf_tree(root*2+1,mid+1,r);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值