ifrog 1129 喵哈哈村的战斗魔法师丶坏坏い月 线段树||分块

题目链接点这里


md,,好久没写线段树了,,犯了很多脑残错误,,哎,,

唔,,,写完还心情好,用分块的做法重新写了遍,,,

主要是怎么查找一个区间内大于大于V的第一个元素,分块比较好想,块内暴力就好了

然后,,线段树那,,有一种想法就是用二分查找这个位置,,比如我现在找[l,m]这个区间最大值是不是大于v,是的话,继续划分[l,m],如果不是大于等于v,继续划分[m+1,r]。

这种正确性很显然。

还有一种,是我写的,,我,,解释不太清楚,,(捂脸

线段树做法:

#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin);
#define mem(x,y) memset(x,y,sizeof(x));
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<x<<endl;
#define MX 111111
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<int,int> PII;
int n,m;
LL maxn[MX<<2],lazy[MX<<2];
void pushup(int rt)
{
    maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    lazy[rt]=0;
    if(l==r)
    {
        scanf("%lld",&maxn[rt]);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        maxn[rt<<1]+=lazy[rt];
        maxn[rt<<1|1]+=lazy[rt];
    }
    lazy[rt]=0;
}
void update(int d,int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        lazy[rt]+=d;
        maxn[rt]+=d;
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(m>=L)update(d,L,R,lson);
    if(m+1<=R) update(d,L,R,rson);
    pushup(rt);
}
int query(int v,int L,int R,int l,int r,int rt)
{
    if(l==r) return l;
    pushdown(rt);
    int m=(l+r)>>1;
    int ans=-1;
    if(m>=L&&maxn[rt<<1]>=v)ans=query(v,L,R,lson);
    if(ans==-1)if(m+1<=R&&maxn[rt<<1|1]>=v) ans=query(v,L,R,rson);
    return ans;
}
int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        cin>>n>>m;
        build(1,n,1);
        for(int i=1; i<=m; i++)
        {
            int opt,l,r,v;
            scanf("%d%d%d%d",&opt,&l,&r,&v);
            if(opt==1)printf("%d\n",query(v,l,r,1,n,1));
            else update(v,l,r,1,n,1);
        }
    }
    return 0;
}


分块的做法(其实差不多就是模拟线段树的,,)

#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin);
#define mem(x,y) memset(x,y,sizeof(x));
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<x<<endl;
#define MX 111111
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<int,int> PII;
int n,m;
int block,blocknum,belong[MX],blockl[MX],blockr[MX];
LL maxn[MX],arr[MX],lazy[MX];
void pushdown(int x)
{
    if(lazy[x])
        for(int i=blockl[x]; i<=blockr[x]; i++)arr[i]+=lazy[x];
    lazy[x]=0;
}
void pushup(int x)
{
    for(int i=blockl[x]; i<=blockr[x]; i++)maxn[x]=max(maxn[x],arr[i]);
}
int main()
{
    int cas;
    cin>>cas;
    while(cas--)
    {
        cin>>n>>m;
        for(int i=1; i<=n; i++)scanf("%lld",&arr[i]);
        block=sqrt(n+0.5);
        blocknum=(n-1)/block+1;
        for(int i=1; i<=n; i++) belong[i]=(i-1)/block+1;
        for(int i=1; i<=blocknum; i++)
        {
            blockl[i]=(i-1)*block+1;
            if(i==blocknum) blockr[i]=n;
            else blockr[i]=i*block;
        }
        for(int i=1; i<=blocknum; i++)maxn[i]=-INF,lazy[i]=0;
        for(int i=1; i<=n; i++)
        {
            maxn[belong[i]]=max(maxn[belong[i]],arr[i]);
        }
        for(int i=1; i<=m; i++)
        {
            int opt,l,r,v;
            scanf("%d%d%d%d",&opt,&l,&r,&v);
            if(opt==1)
            {
                int x=-1;
                if(belong[l]==belong[r])
                {
                    pushdown(belong[l]);
                    for(int i=l; i<=r; i++)if(arr[i]>=v)
                        {
                            x=i;
                            break;
                        }
                }
                else
                {
                    pushdown(belong[l]);
                    for(int i=l; i<=blockr[belong[l]]; i++)
                    {
                        if(arr[i]>=v)
                        {
                            x=i;
                            break;
                        }
                    }
                    if(x==-1)for(int i=belong[l]+1; i<=belong[r]-1; i++)
                        {
                            if(maxn[i]>=v)
                            {
                                pushdown(i);
                                for(int j=blockl[i]; j<=blockr[i]; j++)
                                {
                                    if(arr[j]>=v)
                                    {
                                        x=j;
                                        break;
                                    }
                                }
                            }
                            if(x!=-1)break;
                        }

                    if(x==-1)
                    {
                        pushdown(belong[r]);
                        for(int i=blockl[belong[r]]; i<=r; i++) if(arr[i]>=v)
                            {
                                x=i;
                                break;
                            }
                    }
                }
                printf("%d\n",x);

            }
            else
            {
                if(belong[l]==belong[r])
                {
                    pushdown(belong[l]);
                    for(int i=l; i<=r; i++) arr[i]+=v;
                    pushup(belong[l]);
                }
                else
                {
                    pushdown(belong[l]);
                    for(int i=l; i<=blockr[belong[l]]; i++)arr[i]+=v;
                    pushup(belong[l]);
                    for(int i=belong[l]+1; i<=belong[r]-1; i++)
                    {
                        lazy[i]+=v;
                        maxn[i]+=v;
                    }
                    pushdown(belong[r]);
                    for(int i=blockl[belong[r]]; i<=r; i++) arr[i]+=v;
                    pushup(belong[r]);
                }
            }
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值