2018暑假杭电多校第二场

1007 (hdu 6315)

http://acm.hdu.edu.cn/showproblem.php?pid=6315

问了yxz后做的。。。
这个是我一般写线段树的方法,才觉得感觉有点麻烦,还是yxz的写法安逸些

#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
using namespace std;
typedef long long LL;
const LL maxn=5e5+5;
int N,M;
int b[maxn];
struct AAA
{
    int L,R,sum,lazy,Min;
};
AAA tree[maxn<<2];
void Build(int id,int L,int R)
{
    tree[id].L=L,tree[id].R=R;
    tree[id].lazy=tree[id].sum=0;
    if(L==R)
    {
        tree[id].Min=b[L];
        return ;
    }
    int mid=L+R>>1;
    Build(id<<1,L,mid);
    Build(id<<1|1,mid+1,R);
    tree[id].Min=min(tree[id<<1].Min,tree[id<<1|1].Min);
}
void pushup(int id)
{
    tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum; 
    tree[id].Min=min(tree[id<<1].Min,tree[id<<1|1].Min);
}
void pushdown(int id)
{
    if(tree[id].lazy==0)return ;
    tree[id<<1].Min-=tree[id].lazy;
    tree[id<<1|1].Min-=tree[id].lazy;
    tree[id<<1].lazy+=tree[id].lazy;
    tree[id<<1|1].lazy+=tree[id].lazy;
    tree[id].lazy=0;
}
void Add(int id,int l,int r,int v)
{
    if(tree[id].L>=l&&tree[id].R<=r)
    {
        if(tree[id].Min>1)//如果最小值大于1,说明这一段区间里面还没有能够计算答案的,就只做个标记 
        {
            tree[id].lazy+=v;
            tree[id].Min-=v;
            return ;
        }
        if(tree[id].L==tree[id].R)//不能计算答案的区间已经过滤掉了,现在只用计算每个答案了 
        {
            tree[id].lazy+=v;
            tree[id].sum=tree[id].lazy/b[tree[id].L];
            tree[id].Min=b[tree[id].L];                 //计算答案后又重新变回b[i] 
            return ;
        }
    }
    pushdown(id);
    int mid=tree[id].L+tree[id].R>>1;
    if(r<=mid)Add(id<<1,l,r,v);          
    else if(l>mid)Add(id<<1|1,l,r,v);
    else 
    {
        Add(id<<1,l,mid,v);
        Add(id<<1|1,mid+1,r,v);
    }
    pushup(id);
}
LL query(int id,int qL,int qR)
{
    if(tree[id].L>=qL&&tree[id].R<=qR)return tree[id].sum;
    int mid=tree[id].L+tree[id].R>>1;
    pushdown(id);
    if(qR<=mid)return query(id<<1,qL,qR);
    else if(qL>mid)return query(id<<1|1,qL,qR);
    else 
    {
        return query(id<<1,qL,mid)+query(id<<1|1,mid+1,qR);
    }
}
void print()//打印出线段树 
{
    for(int i=1;i<4*N;i++)
    {
        cout<<"id="<<i<<" Min="<<tree[i].Min<<" sum="<<tree[i].sum<<" lazy="<<tree[i].lazy<<"  |  ";
        if((i&(i+1))==0)cout<<endl;
    }
    cout<<endl;
}
int main()
{

    while(cin>>N>>M)
    {
        for(int i=1;i<=N;i++)scanf("%d",&b[i]);
        Build(1,1,N);
        char cmd[10];
        int L,R;
        while(M--)
        {
            scanf("%s%d%d",cmd,&L,&R);
            if(cmd[0]=='a')
            {
                Add(1,L,R,1);

            }
            else 
            {
                printf("%d\n",query(1,L,R));
            }
        }

    } 

}

yxz的写法

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const LL maxn=1e5+5;
int b[maxn];
int lazy[maxn<<2];              //用来记录对答案的贡献 
int mi[maxn<<2],sum[maxn<<2];
int N,M;
void Build(int id,int L,int R)
{
    sum[id]=0;
    lazy[id]=0;
    if(L==R)
    {
        mi[id]=b[L];
        return ;
    }
    int mid=L+R>>1;
    Build(id<<1,L,mid);
    Build(id<<1|1,mid+1,R);
    mi[id]=min(mi[id<<1],mi[id<<1|1]);
}
void pushdown(int id)
{
    if(lazy[id]==0)return ;
    lazy[id<<1]+=lazy[id];
    lazy[id<<1|1]+=lazy[id];
    mi[id<<1]-=lazy[id];
    mi[id<<1|1]-=lazy[id];
    lazy[id]=0;
}
void pushup(int id)
{
    mi[id]=min(mi[id<<1],mi[id<<1|1]);
    sum[id]=sum[id<<1]+sum[id<<1|1];
}
void Add(int id,int L,int R,int qL,int qR,int v)
{
//  cout<<"di="<<id<<" L="<<L<<" R="<<R<<endl;
    if(qL<=L&&qR>=R)
    {
        if(mi[id]>1)            //如果落到了某个线段上,而最小值不满足条件,就直接加在lazy上面,不用继续往下加了 
        {
            lazy[id]+=v;
            mi[id]--;
            return ;
        }
        if(L==R)                //如果到了最底层,就计算答案 
        {
            lazy[id]+=v;
            sum[id]=lazy[id]/b[L];
            mi[id]=b[L];
            return ;
        } 
    }
    pushdown(id);
    int mid=L+R>>1;
    if(qL<=mid)Add(id<<1,L,mid,qL,qR,v);
    if(qR>=mid+1)Add(id<<1|1,mid+1,R,qL,qR,v);
    pushup(id);
}
int query(int id,int L,int R,int qL,int qR)
{
    if(qL<=L&&qR>=R)return sum[id];
    pushdown(id);
    int mid=L+R>>1;
    int res=0;
    if(qL<=mid)res+=query(id<<1,L,mid,qL,qR);
    if(qR>=mid+1)res+=query(id<<1|1,mid+1,R,qL,qR);
    return res;
}
int main()
{
    while(cin>>N>>M)
    {
        for(int i=1;i<=N;i++)scanf("%d",&b[i]);
        char cmd[10];
        int L,R;
        Build(1,1,N);
        for(int i=1;i<=M;i++)
        {
            scanf("%s%d%d",cmd,&L,&R);
            if(cmd[0]=='a')
            {
                Add(1,1,N,L,R,1);
            }
            else 
            {
                printf("%d\n",query(1,1,N,L,R));
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/SwustLpf/article/details/81264689