zoukankan      html  css  js  c++  java
  • [BZOJ 4826][Hnoi2017]影魔(主席树)

    Description

    影魔,奈文摩尔,据说有着一个诗人的灵魂。事实上,他吞噬的诗人灵魂早已成千上万。千百年来,他收集了各式各样
    的灵魂,包括诗人、牧师、帝王、乞丐、奴隶、罪人,当然,还有英雄。每一个灵魂,都有着自己的战斗力,而影魔,靠
    这些战斗力提升自己的攻击。奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n。
    第 i个灵魂的战斗力为 k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对 i,j(i<j)来说,若不存在 k[s](i
    <s<j)大于 k[i]或者 k[j],则会为影魔提供 p1 的攻击力(可理解为:当 j=i+1 时,因为不存在满足 i<s<j 的 s,从
    而 k[s]不存在,这时提供 p1 的攻击力;当 j>i+1 时,若max{k[s]|i<s<j}<=min{k[i],k[j]} , 则 提 供 p1 的 攻
     击 力 ); 另 一 种 情 况 , 令 c 为k[i+1],k[i+2],k[i+3]......k[j-1]的最大值,若 c 满足:k[i]<c<k[j],或
    者 k[j]<c<k[i],则会为影魔提供 p2 的攻击力,当这样的 c 不存在时,自然不会提供这 p2 的攻击力;其他情况的
    点对,均不会为影魔提供攻击力。影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任
    意一段区间[a,b],1<=a<b<=n,位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑 所有满足a<=i<j<=b 的灵
    魂对 i,j 提供的攻击力之和。顺带一提,灵魂的战斗力组成一个 1 到 n 的排列:k[1],k[2],...,k[n]。

    Solution

    单调栈可求出位置i左边第一个比它大的位置L[i]和右边第一个比它大的位置R[i]

    可以知道点对(L[i],R[i])提供p1的攻击力

    L[i]+1~i-1与R[i]组成的点对提供p2的攻击力

    L[i]与i+1~R[i]-1组成的点对提供p2的攻击力

    于是用主席树维护,新加入一个点作为左端点或右端点时的攻击力

    还要加上相邻的每两个点对的攻击力p1

    WA调了好久,还怀疑是有些地方没开LL,后来发现是数组越界了…开大一点就好了//话说为什么不是RE

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 200005
    #define INF 0x3f3f3f3f
    typedef long long LL;
    using namespace std;
    int n,m,p1,p2,k[MAXN];
    int s[MAXN],top,L[MAXN],R[MAXN],head1[MAXN],cnt1=0,head2[MAXN],cnt2=0;
    struct Node
    {
        int l,r,w,next;
    }x[MAXN*4],y[MAXN*4];
    void add1(int u,int l,int r,int w)
    {
        x[++cnt1].next=head1[u];
        head1[u]=cnt1;
        x[cnt1].l=l,x[cnt1].r=r,x[cnt1].w=w;
    }
    void add2(int u,int l,int r,int w)
    {
        y[++cnt2].next=head2[u];
        head2[u]=cnt2;
        y[cnt2].l=l,y[cnt2].r=r,y[cnt2].w=w;
    }
    struct fotile_tree
    {
        int rt[MAXN],ls[MAXN*50],rs[MAXN*50],tot;
        LL atk[MAXN*50],val[MAXN*50];
        fotile_tree(){tot=0;}
        void build(int &idx,int l,int r)
        {
            ++tot,idx=tot;
            atk[idx]=val[idx]=0;
            if(l==r)return;
            int mid=(l+r)>>1;
            build(ls[idx],l,mid);
            build(rs[idx],mid+1,r);
        }
        void insert(int &idx,int last,int l,int r,int x,int y,int v)
        {
            if(x>y)return;
            ++tot,idx=tot;
            atk[idx]=atk[last]+1LL*(y-x+1)*v,val[idx]=val[last];
            ls[idx]=ls[last],rs[idx]=rs[last];
            if(l==x&&r==y){val[idx]+=v;return;}
            int mid=(l+r)>>1;
            if(y<=mid)insert(ls[idx],ls[last],l,mid,x,y,v);
            else if(x>mid)insert(rs[idx],rs[last],mid+1,r,x,y,v);
            else {insert(ls[idx],ls[last],l,mid,x,mid,v);insert(rs[idx],rs[last],mid+1,r,mid+1,y,v);}
        }
        LL query(int s,int t,int l,int r,int x,int y)
        {
            if(x>y)return 0; 
            if(l==x&&r==y)return atk[t]-atk[s];
            int mid=(l+r)>>1;
            LL calc=1LL*(y-x+1)*(val[t]-val[s]);
            if(y<=mid){return calc+query(ls[s],ls[t],l,mid,x,y);}
            else if(x>mid)return calc+query(rs[s],rs[t],mid+1,r,x,y);
            else return calc+query(ls[s],ls[t],l,mid,x,mid)+query(rs[s],rs[t],mid+1,r,mid+1,y);
        }
    }trL,trR;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-')f=-1;c=getchar();
        }
        while(c>='0'&&c<='9'){
            x=x*10+c-'0';c=getchar();
        }
        return x*f;
    }
    int main()
    {
        memset(head1,-1,sizeof(head1));
        memset(head2,-1,sizeof(head2));
        n=read(),m=read(),p1=read(),p2=read();
        for(int i=1;i<=n;i++)k[i]=read();
        top=0;
        for(int i=1;i<=n;i++)
        {
            while(top&&k[s[top]]<k[i])R[s[top]]=i,top--;
            s[++top]=i;
        }
        while(top)R[s[top]]=n+1,top--;
        top=0;
        for(int i=n;i>0;i--)
        {
            while(top&&k[s[top]]<k[i])L[s[top]]=i,top--;
            s[++top]=i;
        }
        while(top)L[s[top]]=0,top--;
        for(int i=1;i<=n;i++)
        {
            add1(L[i],R[i],R[i],p1);
            add1(L[i],i+1,R[i]-1,p2);
            add2(R[i],L[i]+1,i-1,p2);
        }
        trL.build(trL.rt[0],1,n);trR.build(trR.rt[n+1],1,n);
        for(int i=1;i<=n;i++)
        {
            trL.rt[i]=trL.rt[i-1];
            for(int j=head1[i];~j;j=x[j].next)
            trL.insert(trL.rt[i],trL.rt[i],1,n,max(1,x[j].l),min(n,x[j].r),x[j].w);
        }
        for(int i=n;i>0;i--)
        {
            trR.rt[i]=trR.rt[i+1];
            for(int j=head2[i];~j;j=y[j].next)
            trR.insert(trR.rt[i],trR.rt[i],1,n,max(1,y[j].l),min(n,y[j].r),y[j].w);
        }
        for(int i=1;i<=m;i++)
        {
            int a=read(),b=read();
            if(a>b)swap(a,b); 
            LL ans=1LL*(b-a)*p1;
            ans+=trL.query(trL.rt[a-1],trL.rt[b],1,n,a,b);
            ans+=trR.query(trR.rt[b+1],trR.rt[a],1,n,a,b);
            printf("%lld
    ",ans);
        }
        return 0;
    } 
  • 相关阅读:
    Spring Boot 学习(一) 快速搭建SpringBoot 项目
    @RunWith和 SpringJUnit4ClassRunner ---->junit4和Spring一起使用
    Spring Boot的SpringApplication类详解
    @SpringBootApplication的使用
    使用阿里云搭建个人博客
    @Controller和@RestController的区别?
    蚂蚁金服开发文档中心
    Logger.getLogger()和LogFactory.getLog()的区别
    SimpleDateFormat使用详解
    SpringBoot整合RabbitMQ实现微服务间的异步消息沟通
  • 原文地址:https://www.cnblogs.com/Zars19/p/6787386.html
Copyright © 2011-2022 走看看