hdu4630&&hdu4638 线段树离线操作

两题都是朴素想法枚举两个端点O(n^2)超时,那么枚举其中一个端点用线段树维护另一个端点。关键在于没插入一个端点后都是成段更新,否则又会退化到O(N^2)。

ps:两题用c++交都比g++快500ms以上。

4630

//#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn=50005;
int tree[maxn<<2],lz[maxn<<2];
void pushdown(int rt)
{
    tree[rt]=max(tree[rt],lz[rt]);
    lz[rt<<1]=max(lz[rt<<1],lz[rt]);
    lz[rt<<1|1]=max(lz[rt<<1|1],lz[rt]);
    lz[rt]=-1;
}
void update(int L,int R,int val,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        lz[rt]=max(lz[rt],val);
        return ;
    }
    int mid=(l+r)>>1;
    if(R<=mid)
    {
        pushdown(rt);
        update(L,R,val,lson);
        tree[rt]=max(tree[rt<<1],lz[rt<<1]);
        tree[rt]=max(tree[rt],max(tree[rt<<1|1],lz[rt<<1|1]));
        return ;
    }
    if(L>mid)
    {
        pushdown(rt);
        update(L,R,val,rson);
        tree[rt]=max(tree[rt<<1],lz[rt<<1]);
        tree[rt]=max(tree[rt],max(tree[rt<<1|1],lz[rt<<1|1]));
        return ;
    }
    pushdown(rt);
    update(L,R,val,lson);
    update(L,R,val,rson);
    tree[rt]=max(tree[rt<<1],lz[rt<<1]);
    tree[rt]=max(tree[rt],max(tree[rt<<1|1],lz[rt<<1|1]));
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return max(tree[rt],lz[rt]);
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    if(R<=mid)
    {
        return query(L,R,lson);
    }
    if(L>mid)
    {
        return query(L,R,rson);
    }
    return max(query(L,R,lson),query(L,R,rson));
}
int a[maxn];
struct qyy
{
    int l,r,id;
    qyy(){}
    qyy(int a,int b,int c)
    {
        l=a;r=b;id=c;
    }
    bool operator< (const qyy &a) const
    {
        return r<a.r;
    }
}qy[maxn];
int qcnt;
struct opt
{
    int ans,id;
    opt(){}
    opt(int a,int b)
    {
        ans=a;id=b;
    }
    bool operator< (const opt &a) const
    {
        return id<a.id;
    }
}opt[maxn];
int ocnt;
int pre[maxn];
int main()
{
    int t,n,m,i,j,l,r,cnt;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        scanf("%d",&m);
        qcnt=0;ocnt=0;
        for(i=1;i<=m;++i)
        {
            scanf("%d%d",&l,&r);
            if(l==r)
            {
                opt[ocnt].ans=0;
                opt[ocnt++].id=i;
            }
            else
            {
                qy[qcnt].id=i;
                qy[qcnt].l=l;
                qy[qcnt++].r=r;
            }
        }
        sort(qy,qy+qcnt);
        memset(pre,-1,sizeof(pre));
        memset(tree,-1,sizeof(tree));
        memset(lz,-1,sizeof(lz));
        cnt=0;
        for(i=1;i<=n;++i)
        {
            for(j=1;j*j<=a[i];++j)
            {
                if(a[i]%j!=0)
                    continue;
                if(pre[j]!=-1)
                {
                    update(1,pre[j],j,1,n,1);
                }
                if(pre[a[i]/j]!=-1)
                {
                    update(1,pre[a[i]/j],a[i]/j,1,n,1);
                }
                pre[j]=i;
                pre[a[i]/j]=i;
            }
            while(cnt<qcnt&&qy[cnt].r==i)
            {
                opt[ocnt].id=qy[cnt].id;
                opt[ocnt++].ans=query(qy[cnt].l,qy[cnt].l,1,n,1);
                cnt++;
            }
            if(cnt==qcnt)
                break;
        }
        sort(opt,opt+m);
        for(i=0;i<m;++i)
        {
            printf("%d\n",opt[i].ans);
        }
    }
    return 0;
}


4638

//#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn=100005;
int tree[maxn<<2],lz[maxn<<2];
void pushdown(int rt)
{
    lz[rt<<1]+=lz[rt];
    lz[rt<<1|1]+=lz[rt];
    lz[rt]=0;
}
void update(int L,int R,int val,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        lz[rt]+=val;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(R<=mid)
    {
        update(L,R,val,lson);
        return ;
    }
    if(L>mid)
    {
        update(L,R,val,rson);
        return ;
    }
    update(L,R,val,lson);
    update(L,R,val,rson);
}
int query(int pos,int l,int r,int rt)
{
    if(l==r)
    {
        return tree[rt]+lz[rt];
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    if(pos<=mid)
        return query(pos,lson);
    else
        return query(pos,rson);
}
bool hash[maxn];
int a[maxn];
struct qyy
{
    int l,r,id;
    qyy(){}
    qyy(int a,int b,int c)
    {
        l=a;r=b;id=c;
    }
    bool operator< (const qyy& a) const
    {
        return r<a.r;
    }
}qy[maxn];
struct optt
{
    int ans,id;
    optt(){}
    optt(int a,int b)
    {
        ans=a;id=b;
    }
    bool operator< (const optt& a) const
    {
        return id<a.id;
    }
}opt[maxn];
int pos[maxn];
int main()
{
    int t,n,m,i,j,l,r,cnt,tmp,tmp2,val,ccnt,ocnt;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            pos[a[i]]=i;
        }
        cnt=0;
        for(i=1;i<=m;++i)
        {
            scanf("%d%d",&l,&r);
            qy[cnt].id=i;qy[cnt].l=l;qy[cnt].r=r;cnt++;
        }
        sort(qy,qy+cnt);
        memset(hash,false,sizeof(hash));
        memset(tree,0,sizeof(tree));memset(lz,0,sizeof(lz));
        ccnt=0,ocnt=0;
        for(r=1;r<=n;++r)
        {
            val=a[r];
            if(!hash[val-1]&&!hash[val+1])
            {
                update(1,r,1,1,n,1);
            }
            else if(hash[val-1]&&!hash[val+1])
            {
                tmp=pos[val-1];
                update(tmp+1,r,1,1,n,1);
            }
            else if(!hash[val-1]&&hash[val+1])
            {
                tmp=pos[val+1];
                update(tmp+1,r,1,1,n,1);
            }
            else if(hash[val-1]&&hash[val+1])
            {
                tmp=min(pos[val-1],pos[val+1]);
                tmp2=max(pos[val-1],pos[val+1]);
                update(1,tmp,-1,1,n,1);
                update(tmp2+1,r,1,1,n,1);
            }
            hash[val]=true;
            while(ccnt<cnt&&qy[ccnt].r==r)
            {
                opt[ocnt].ans=query(qy[ccnt].l,1,n,1);
                opt[ocnt].id=qy[ccnt].id;
                ocnt++;ccnt++;
            }
            if(ccnt==cnt)
                break;
        }
        sort(opt,opt+ocnt);
        for(i=0;i<ocnt;++i)
        {
            printf("%d\n",opt[i].ans);
        }
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值