1 条题解

  • 0
    @ 2025-8-24 21:52:02

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 花样百出
    **

    搬运于2025-08-24 21:52:02,当前版本为作者最后更新于2017-12-21 21:03:32,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题解:

    这个题可以采取离线处理的方式.先处理出每个点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的贡献.③

    所以我们离线排序处理好.

    对于①情况,我们在扫到R[i]时,更新点L[i]的贡献

    对于②情况,我们在扫到R[i]时,更新区间L[i]+1到i-1的贡献

    对于③情况,我们在扫到L[i]时,更新区间i+1到R[i]-1的贡献

    我们对于每个询问[l,r],在扫到l-1时,我们记录此时区间l到r的每个点的贡献和为sum1,然后当我们扫到r的时候,再次记录此时的区间l到r的每个点的贡献和为sum2,显然答案就是sum2-sum1了.

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<set>
    #define RG register
    #define LL long long int
    #define MAXN 500010
    using namespace std;
    const int INF=1e9;
    struct node{
      int l,r,x,id,v;
      node(){}
      node(int l_,int r_,int x_,int id_,int v_):l(l_),r(r_),x(x_),id(id_),v(v_){}
      bool operator <(const node &tmp)const{
        return x<tmp.x;
      }
    }s1[MAXN],s2[MAXN];
    int n,m,p1,p2;
    int k[MAXN],q[MAXN],top;
    int L[MAXN],R[MAXN];
    LL ans[MAXN],c1[MAXN],c2[MAXN];
    int lowbit(int x)
    {
      return x&(-x);
    }
    void add(int x,int y)//区间修改操作
    {
      if(x) for(int i=x;i<=n;i+=lowbit(i)) c1[i]+=y,c2[i]+=(LL)x*y;
    }
    LL sum(int x)
    {
      LL num=0;
      for(int i=x;i>0;i-=lowbit(i)) num+=(x+1)*c1[i]-c2[i];
      return num;
    }
    int main()
    {
      freopen("1.in","r",stdin);
      scanf("%d%d%d%d",&n,&m,&p1,&p2);
      k[0]=k[n+1]=n+1;q[++top]=0;
      for(int i=1;i<=n;i++) scanf("%d",&k[i]);
      for(int i=1;i<=n+1;i++)
        {
          while(k[q[top]]<k[i]) R[q[top]]=i,top--;
          L[i]=q[top];q[++top]=i;
        }
      int x,y;
      for(int i=1;i<=m;i++)
        {
          scanf("%d%d",&x,&y);ans[i]+=(y-x)*p1;
          s1[i]=node(x,y,x-1,i,-1);s1[i+m]=node(x,y,y,i,1);
        }
      sort(s1+1,s1+2*m+1);int tot=0;
      for(int i=1;i<=n;i++)
        {
          if(1<=L[i]&&R[i]<=n) s2[++tot]=node(L[i],L[i],R[i],0,p1);
          if(1<=L[i]&&R[i]>i+1) s2[++tot]=node(i+1,R[i]-1,L[i],0,p2);
          if(L[i]+1<i&&R[i]<=n) s2[++tot]=node(L[i]+1,i-1,R[i],0,p2);
        }
      sort(s2+1,s2+tot+1);int n1=1,n2=1;
      while(!s1[n1].x) n1++;
      for(int i=1;n1<=m*2&&i<=n;i++)
        {
          while(n2<=tot&&s2[n2].x==i){
        add(s2[n2].r+1,-s2[n2].v);
        add(s2[n2].l,s2[n2].v);
        n2++;
          }
          while(n1<=m*2&&s1[n1].x==i){
        ans[s1[n1].id]+=s1[n1].v*(sum(s1[n1].r)-sum(s1[n1].l-1));
        n1++;
          } 
        }
      for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
      return 0;
    }
    
    • 1

    信息

    ID
    2717
    时间
    2000ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者