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

    题目链接

    单调栈&线段树

    离线处理询问,首先用单调栈预处理出左边第一个大于它的数head[i]及右边第一个大于它的数tail[i],然后从左到右及从右到左各进行一遍下述操作:

    从右到左枚举一个点i,作为区间的左端点,然后对于i+1到tail[i]在线段树中全部加上p2,若tail[i]不等于n+1就把tail[i]加上p1-2*p2 (因为[i,tail[i]]这个区间是要加上p1的,而正反各做一次却加上了两个p2) 。

    若有一个以i为左端点的询问,则把这个询问的答案加上1~询问右端点的和。可以自己举几个例子,发现这样是可以处理到每一个区间对答案的贡献的。

    复杂度O(nlogn)。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #include<bitset>
    #include<cmath>
    #define P puts("lala")
    #define pc cerr<<"lala"<<endl
    #define HH puts("")
    #define pb push_back
    #define pf push_front
    #define fi first
    #define se second 
    #define mkp make_pair
    using namespace std;
    inline void read(int &re)
    {
        char ch=getchar();int g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        re*=g;
    }
    typedef long long ll;
    inline void read(ll &re)
    {
        char ch=getchar();ll g=1;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        re=0;
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
        re*=g;
    }
    const int N=200050;
    int n,m,p1,p2;
    int att[N];
    int st[N],top=0;
    int add[N<<2],head[N],tail[N];
    ll sum[N<<2];
    
    inline void pushdown(int o,int l,int r)
    {
        if(add[o])
        {
            add[o<<1]+=add[o];add[o<<1|1]+=add[o];
            int mid=l+r>>1;
            sum[o<<1]+=(ll)(mid-l+1)*add[o];sum[o<<1|1]+=(ll)(r-mid)*add[o];
            add[o]=0;
        }    
    }
    
    void update(int o,int l,int r,int x,int y,int k)
    {
        if(x<=l&&r<=y)
        {
            add[o]+=k;
            sum[o]+=(ll)(r-l+1)*k;
            return ;
        }
        pushdown(o,l,r);
        int mid=l+r>>1;
        if(x<=mid) update(o<<1,l,mid,x,y,k);
        if(y>mid) update(o<<1|1,mid+1,r,x,y,k);
        sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    
    ll query(int o,int l,int r,int x,int y)
    {
        if(x<=l&&r<=y) return sum[o];
        pushdown(o,l,r);
        int mid=l+r>>1;
        ll ans=0;
        if(x<=mid) ans+=query(o<<1,l,mid,x,y);
        if(y>mid) ans+=query(o<<1|1,mid+1,r,x,y);
        sum[o]=sum[o<<1]+sum[o<<1|1];
        return ans;
    }
    
    struct node
    {
        int l,r;
        ll ans;
    }qr[N];
    bool cmp1(node a,node b)
    {
        return a.l<b.l;
    }
    bool cmp2(node a,node b)
    {
        return a.r>b.r;
    }
    
    vector<int>ve1[N],ve2[N];
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
        int i,j,opt,T;
        read(n);read(m);read(p1);read(p2);
        for(i=1;i<=n;++i) read(att[i]);
        for(i=n;i;--i)
        {
            if(!top) st[++top]=i;
            else
            {
                while(top&&att[st[top]]<att[i]) top--;
                if(top) tail[i]=st[top];
                st[++top]=i;
            }
        }
        memset(st,0,sizeof(st));
        top=0;
    
        for(i=1;i<=n;++i)
        {
            if(!top) st[++top]=i;
            else
            {
                while(top&&att[st[top]]<att[i]) top--;
                if(top) head[i]=st[top];
                st[++top]=i;
            }
        }
        
        for(i=1;i<=m;++i)
        {
            read(qr[i].l);read(qr[i].r);
            ve1[qr[i].l].pb(i);ve2[qr[i].r].pb(i);
            qr[i].ans=0;
        }
    
        for(i=1;i<=n;++i)
        {
            j=(head[i]?head[i]:1);
            if(j!=i) update(1,1,n,j,i-1,p2);
            if(head[i]) update(1,1,n,head[i],head[i],p1-2*p2);
            int siz=ve2[i].size();
            for(int o=0;o<siz;++o)
            {
                int u=ve2[i][o];
                qr[u].ans+=query(1,1,n,qr[u].l,n);
            }
        }
    
        memset(add,0,sizeof(add));memset(sum,0,sizeof(sum));
    
        for(i=n;i;--i)
        {
            j=(tail[i]?tail[i]:n);
            if(j!=i) update(1,1,n,i+1,j,p2);
            if(tail[i]) update(1,1,n,tail[i],tail[i],p1-2*p2);
            int siz=ve1[i].size();
            for(int o=0;o<siz;++o)
            {
                int u=ve1[i][o];
                qr[u].ans+=query(1,1,n,1,qr[u].r);
            }
        }
    
        for(i=1;i<=m;++i) printf("%lld
    ",qr[i].ans);
        return 0;
    }
    /*
    
    */
  • 相关阅读:
    将博客搬至CSDN
    神州笔记本电脑【K670D】安装 Ubuntu18.04 系列操作
    ValueError: Unknown label type: 'continuous'
    Spark: JAVA_HOME is not set
    IDEA 搭建 Spark 源码 (Ubuntu)
    XX-Net 解决IPV6 不稳定,时好时坏。
    解决SBT下载慢,dump project structure from sbt?
    pip install kaggle 出现 【网络不可达】?
    Git clone 克隆Github上的仓库,速度慢?
    进程间的通信方式
  • 原文地址:https://www.cnblogs.com/thkkk/p/7837369.html
Copyright © 2011-2022 走看看