【BZOJ4826】【HNOI2017】影魔

来源:互联网 发布:ebsco数据库免费入口 编辑:程序博客网 时间:2024/04/28 06:59

题目描述

给定一个长度n2×105的序列a,对于点对(i,j)若不存在i<k<j使得a[i]<a[k]a[j]<a[k],若存在i<k<j使得a[i]<a[k]a[k]<a[j]时,点对向答案贡献p2
现在有m2×105个询问,每次查询区间[a,b]中的点对向答案的贡献之和。

题目解析

首先,我们的第一想法就枚举每一个位置作为k,看左边有多少个小于/大于,右边有多少个小于/大于a[k],两边乘起来就是p1,p2的数量,如果我们在想一想,若设位置i左边比他大的第一个为li,右边第一个比他大的是ri。则对于贡献p1,位置i产生的点对便是(li,ri),注意只产生一个,至于为什么,我们可以这样理解:若li左端还有一个l,使得(l,ri)组成一个贡献点对,那么此时(l,ri)间的最大值是li,即我们一定在li处讨论过了;对于贡献p2,我们也只考虑(li,i+1ri1)(li+1i1,ri)的点对。

又因为我们对于每一个询问都需要回答,于是我们便可以将贡献点对映射到x,y轴上,用主席树维护区间增加,区间查询,至于在x轴上区间加可以转换为在另一棵树上y轴上区间加。

代码

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<stack>using namespace std;#define MAXN 200000#define MAXLOG 18#define MAXM 200000#define INF 0x3f3f3f3ftypedef long long int LL;template<class T>void Read(T &x){    x=0;char c=getchar();bool flag=0;    while(c<'0'||'9'<c){if(c=='-')flag=1;c=getchar();}    while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}    if(flag)x=-x;}struct node{    LL val,lazy;    int ls,rs;}Leaf[MAXM*MAXLOG*5+100];int New_Leaf=0;int NewNode(){    int x=++New_Leaf;    Leaf[x].ls=Leaf[x].rs=Leaf[x].val=Leaf[x].lazy=0;    return x;}void insert(int ll,int rr,int l,int r,int w,int &x,int last){    x=NewNode();    Leaf[x]=Leaf[last];    if(ll==l&&rr==r){        Leaf[x].lazy+=w;        return;    }    else{        Leaf[x].val+=1ll*w*(r-l+1);        int mid=(ll+rr)>>1;        if(r<=mid)insert(ll,mid,l,r,w,Leaf[x].ls,Leaf[last].ls);        else if(mid<l)insert(mid+1,rr,l,r,w,Leaf[x].rs,Leaf[last].rs);        else insert(ll,mid,l,mid,w,Leaf[x].ls,Leaf[last].ls),             insert(mid+1,rr,mid+1,r,w,Leaf[x].rs,Leaf[last].rs);    }}LL query(int ll,int rr,int l,int r,int x){    if(!x)return 0;    if(l<=ll&&rr<=r)        return Leaf[x].val+Leaf[x].lazy*(rr-ll+1);    else{        int mid=(ll+rr)>>1;        if(r<=mid)return Leaf[x].lazy*(r-l+1)+query(ll,mid,l,r,Leaf[x].ls);        else if(mid<l)return Leaf[x].lazy*(r-l+1)+query(mid+1,rr,l,r,Leaf[x].rs);        else return Leaf[x].lazy*(r-l+1)+query(ll,mid,l,mid,Leaf[x].ls)+query(mid+1,rr,mid+1,r,Leaf[x].rs);    }}int root1[MAXN+10],root2[MAXN+10];int A[MAXN+10];int l[MAXN+10],r[MAXN+10];int n,m,p1,p2;stack<int>stk;struct abcd{    int l,r,w;    abcd(){}    abcd(int a,int b,int c):l(a),r(b),w(c){}};vector<abcd>hehe1[MAXN+10],hehe2[MAXN+10];void init(){    while(!stk.empty())stk.pop();    stk.push(1),l[1]=0;    for(int i=2;i<=n;++i){        while(!stk.empty()&&A[stk.top()]<A[i])r[stk.top()]=i,stk.pop();        if(stk.empty())l[i]=0;        else l[i]=stk.top();        stk.push(i);    }    while(!stk.empty())r[stk.top()]=n+1,stk.pop();    for(int i=1;i<=n;++i)hehe1[i].clear(),hehe2[i].clear();    for(int i=1;i<=n;++i){        //printf("[%d] l:%d r:%d\n",i,l[i],r[i]);        if(l[i]>0&&r[i]<=n)hehe1[l[i]].push_back(abcd(r[i],r[i],p1));        if(l[i]>0&&i<r[i]-1)hehe1[l[i]].push_back(abcd(i+1,r[i]-1,p2));        if(r[i]<=n&&i>l[i]+1)hehe2[r[i]].push_back(abcd(l[i]+1,i-1,p2));    }}int main(){    Read(n),Read(m),Read(p1),Read(p2);    for(int i=1;i<=n;++i)Read(A[i]);    init();    memset(root1,0,sizeof(root1));    memset(root2,0,sizeof(root2));    for(int i=1;i<=n;++i){        root1[i]=root1[i-1];        for(int j=0;j<hehe1[i].size();++j){            insert(1,n,hehe1[i][j].l,hehe1[i][j].r,hehe1[i][j].w,root1[i],root1[i]);            //printf("Line1 : %d (%d->%d) w:%d\n",i,hehe1[i][j].l,hehe1[i][j].r,hehe1[i][j].w);        }        if(i<n)insert(1,n,i+1,i+1,p1,root1[i],root1[i]);    }    for(int i=1;i<=n;++i){        root2[i]=root2[i-1];        for(int j=0;j<hehe2[i].size();++j){            insert(1,n,hehe2[i][j].l,hehe2[i][j].r,hehe2[i][j].w,root2[i],root2[i]);            //printf("Line2 : %d (%d->%d) w:%d\n",i,hehe2[i][j].l,hehe2[i][j].r,hehe2[i][j].w);        }    }    int a,b;    LL ans;    for(int i=1;i<=m;++i){        Read(a),Read(b);        ans=0;        ans+=query(1,n,a,b,root1[b]);        ans-=query(1,n,a,b,root1[a-1]);//printf("%I64d\n",ans);        ans+=query(1,n,a,b,root2[b]);        ans-=query(1,n,a,b,root2[a-1]);        printf("%lld\n",ans);    }}
原创粉丝点击