zoukankan      html  css  js  c++  java
  • HNOI2017影魔

    影魔
    • 这么简单的方法尽然想不到,我是真的菜
    • 对每个点,用单调栈的方式处理出他左右第一个比他大的数的位置,你可以把(0)(n+1)设成(inf)
    • 显然对于每对(lef[i])(rig[i])都会做出(p1)的贡献
    • 每个(lef[i])会对(i+1)(rig[i]-1)做出(p2)贡献
    • 同理,每个(rig[i])都会给(lef[i]+1)(i-1)做出(p2)贡献
    • 用结构体存下来,按顺序用线段树将贡献加入即可
    • 统计贡献,对于每个询问(l-r)在扫到(l-1)时将这段区间减去,在扫到(r)时再将这段区间贡献加上即可
    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    using namespace std;
    typedef int sign;
    typedef long long ll;
    #define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
    #define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
    const int N=2e5+5;
    bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
    bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
    template<typename T>inline T read()
    {
        T f=1,ans=0;
        char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
        return ans*f;
    }
    template<typename T>inline void write(T x,char y)
    {
        if(x==0)
        {
            putchar('0');putchar(y);
            return;
        }
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        static char wr[20];
        int top=0;
        for(;x;x/=10)wr[++top]=x%10+'0';
        while(top)putchar(wr[top--]);
        putchar(y);
    }
    void file()
    {
        #ifndef ONLINE_JUDGE
            freopen("3722.in","r",stdin);
            freopen("3722.out","w",stdout);
        #endif
    }
    int n,m,p1,p2;
    int a[N];
    struct Q
    {
        int l,r,x,tag,id;
        bool operator < (const Q &s)const {return x<s.x;} 
    }opt[N<<2];
    int cnt;
    ll ans[N];
    void input()
    {
        int l,r;
        n=read<int>();m=read<int>();p1=read<int>();p2=read<int>();
        For(i,1,n)a[i]=read<int>();
        For(i,1,m)
        {
            l=read<int>();r=read<int>();
            ans[i]+=1ll*(r-l)*1ll*p1;
            opt[++cnt]=(Q){l,r,l-1,-1,i};
            opt[++cnt]=(Q){l,r,r,1,i};
        }
    }
    const int inf=0x3f3f3f3f;
    namespace Tree
    {
        #define mid ((l+r)>>1)
        #define lson h<<1,l,mid
        #define rson h<<1|1,mid+1,r
        ll sum[N<<2],lazy[N<<2];
        void push_up(int h)
        {
            sum[h]=sum[h<<1]+sum[h<<1|1];
        }
        void push_down(int h,int l,int r)
        {
            if(!lazy[h])return;
            int ls=h<<1,rs=ls|1;
            lazy[ls]+=lazy[h];lazy[rs]+=lazy[h];
            sum[ls]+=lazy[h]*1ll*(mid-l+1);
            sum[rs]+=lazy[h]*1ll*(r-mid);
            lazy[h]=0;
        }
        void update(int h,int l,int r,int s,int t,ll v)
        {
            if(s<=l&&r<=t)
            {
                lazy[h]+=v;
                sum[h]+=1ll*v*1ll*(r-l+1);
            }
            else
            {
                push_down(h,l,r);
                if(s<=mid)update(lson,s,t,v);
                if(mid<t)update(rson,s,t,v);
                push_up(h);
            }
        }
        ll query(int h,int l,int r,int s,int t)
        {
            if(s<=l&&r<=t)return sum[h];
            push_down(h,l,r);
            ll res=0;
            if(s<=mid)res=query(lson,s,t);
            if(mid<t)res+=query(rson,s,t);
            push_up(h);
            return res;
        }
    }
    #define rg register
    int lef[N],rig[N];
    struct node
    {
        int l,r,x;
        ll v;
        bool operator < (const node &s)const {return x<s.x;}
    }e[N<<2];
    int sz;
    void init()
    {
        int j;
        sort(opt+1,opt+cnt+1);
        a[0]=a[n+1]=inf;
        For(i,1,n)
        {
            for(j=i-1;j>=0;j=lef[j])if(a[j]>a[i])break;
            lef[i]=j;
        }
        Fordown(i,n,1)
        {
            for(j=i+1;j<=n+1;j=rig[j])if(a[j]>a[i])break;
            rig[i]=j;
        }
        //For(i,1,n)cout<<lef[i]<<' '<<rig[i]<<endl;
        For(i,1,n)
        {
            if(lef[i]+1<i&&rig[i]<=n)e[++sz]=(node){lef[i]+1,i-1,rig[i],p2};
            if(1<=lef[i]&&rig[i]>i+1)e[++sz]=(node){i+1,rig[i]-1,lef[i],p2};
            if(1<=lef[i]&&rig[i]<=n)e[++sz]=(node){lef[i],lef[i],rig[i],p1};
        }
        sort(e+1,e+sz+1);
    }
    void work()
    {
        int pos1=1,pos2=1;
        while(pos2<=cnt&&!opt[pos2].x)pos2++;
        //cerr<<pos2<<' '<<cnt<<endl;
        For(i,1,n)
        {
            for(;pos1<=sz&&e[pos1].x==i;++pos1)
                Tree::update(1,0,n,e[pos1].l,e[pos1].r,e[pos1].v);
            for(;pos2<=cnt&&opt[pos2].x==i;++pos2)
                ans[opt[pos2].id]+=Tree::query(1,0,n,opt[pos2].l,opt[pos2].r)*opt[pos2].tag;
        }
        For(i,1,m)write(ans[i],'
    ');
    }
    int main()
    {
        file();
        input();
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    SpringMVC源码阅读-通过画图理解初始化(十一)
    通过Stratus 服务器在Flash Player中使用RTMFP 开发P2P应用
    Lucene 学习资料
    LIRe 源代码分析 3:基本接口(ImageSearcher)
    LIRe 源代码分析 2:基本接口(DocumentBuilder)
    LIRe 源代码分析 1:整体结构
    Media Player Classic
    ffdshow 源代码分析 5: 位图覆盖滤镜(总结)
    ITU-T Technical Paper: 测量QoS的基本网络模型
    ITU-T Technical Paper: QoS 测量 (目标,方法,协议)
  • 原文地址:https://www.cnblogs.com/dengyixuan/p/8361947.html
Copyright © 2011-2022 走看看