zoukankan      html  css  js  c++  java
  • BZOJ4826: [Hnoi2017]影魔

    4826: [Hnoi2017]影魔

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 550  Solved: 300
    [Submit][Status][Discuss]

    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]。

    Input

    第一行 n,m,p1,p2
    第二行 n 个数:k[1],k[2],...,k[n]
    接下来 m 行,每行两个数 a,b,表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。
    1 <= n,m <= 200000;1 <= p1,p2 <= 1000

    Output

    共输出 m 行,每行一个答案,依次对应 m 个询问。

    Sample Input

    10 5 2 3
    7 9 5 1 3 10 6 8 2 4
    1 7
    1 9
    1 3
    5 9
    1 5

    Sample Output

    30
    39
    4
    13
    16
    思路{
      和去年的序列有点像啊...
      对于一个点,单独计算其作为区间最大值的贡献,这也是一般的序列问题的套路。
      对于单点$ i $,他所能作为一段区间内的最大值所能做出的贡献是什么,
      找出左边第一个大于$K_i$的位置$L_i$,
      右边第一个大于$K_i$的位置$R_i$
      一段区间做出的贡献,又十分自然想到了扫描线.
      由于设二维平面上的点$( x , y ) $  中$ y $值表示所代表的点.$x$值表示它所能够影响到的点。
      $P_1$对应了点$ ( i , L_i ) $到$ ( i , R_i ) $的线段,
      $P_2$对应了点$ ( L_i , i + 1 ) $到$ ( i , R_i - 1 ) $的线段,
      $P_2$对应了点$ ( R_i , L_i + 1 ) $到$ ( R_i , i - 1 ) $的线段,
      询问抽象成两条平行于 $ x $ 轴的线段,
      每条线段左右端点即为所产生的贡献范围.那线段的左右端点和上下端点都是$L,R$了.
      那么就是求询问所代表的区间内的权值和了!!
      用扫描线+区间修改树状数组维护这个东西即可.
      这么说来应该也可以用扫描线来解决去年的序列了.
    }
    #include<bits/stdc++.h>
    #define il inline
    #define RG register
    #define ll long long
    #define db double
    #define N 200010
    #define lowbit (i&-i)
    using namespace std;
    int l[N],r[N],st[N],a[N],n,m,p1,p2;
    ll Ans[N];
    namespace BIT{
      ll t1[N],t2[N];
      void clear(){memset(t1,0,sizeof(t1));memset(t2,0,sizeof(t2));}
      void add(int x,int y){
        for(int i=x;i<=n;i+=lowbit)t1[i]+=y,t2[i]+=1ll*x*y;
      }
      void Insert(int l,int r,int num){
        add(l,num),add(r+1,-num);
      }
      ll Query(int pos){
        ll Sum(0);
        for(int i=pos;i;i-=lowbit)Sum+=(pos+1)*t1[i]-t2[i];
        return Sum;
      }
      ll sum(int l,int r){
        return Query(r)-Query(l-1);
      }
    }
    struct event{
      int l,r,h,bel,val;
      event() {}
      event(int a,int b,int c,int d,int e):l(a),r(b),h(c),bel(d),val(e) {}
    }eve1[N*2],eve2[N*3];int tot1,tot2;
    bool comp(const event & a,const event & b){return a.h<b.h;}
    int main(){
      scanf("%d%d%d%d",&n,&m,&p1,&p2);
      for(int i=1;i<=n;++i)scanf("%d",&a[i]);
      for(int i=1;i<=n;++i){
        while(st[0]&&a[st[st[0]]]<a[i])r[st[st[0]--]]=i;
        st[++st[0]]=i;
      }
      while(st[0])r[st[st[0]--]]=n+1;
      for(int i=n;i;i--){
        while(st[0]&&a[st[st[0]]]<a[i])l[st[st[0]--]]=i;
        st[++st[0]]=i;
      }
      while(st[0])l[st[st[0]--]]=0;
      for(int i=1;i<=m;++i){int l,r;
        scanf("%d%d",&l,&r);Ans[i]+=1ll*(r-l)*p1;
        eve1[++tot1]=event(l,r,r,i,1);
        eve1[++tot1]=event(l,r,l-1,i,-1);
      }
      sort(eve1+1,eve1+tot1+1,comp);
      for(int i=1;i<=n;++i){
        if(l[i]&&r[i]!=n+1)eve2[++tot2]=event(l[i],l[i],r[i],0,p1);
        if(l[i]&&r[i]>i+1)eve2[++tot2]=event(i+1,r[i]-1,l[i],0,p2);
        if(r[i]!=n+1&&l[i]+1<i)eve2[++tot2]=event(l[i]+1,i-1,r[i],0,p2);
      }
      sort(eve2+1,eve2+tot2+1,comp);
      int h1(1),h2(1);
      while(!eve1[h1].h)h1++;
      for(int i=1;i<=n&&h1<=tot1;++i){
        while(h2<=tot2&&eve2[h2].h==i){
          BIT::Insert(eve2[h2].l,eve2[h2].r,eve2[h2].val);
          h2++;
        }
        while(h1<=tot1&&eve1[h1].h==i){
          Ans[eve1[h1].bel]+=eve1[h1].val*(BIT::sum(eve1[h1].l,eve1[h1].r));
          h1++; 
        }
      }
      for(int i=1;i<=m;++i)cout<<Ans[i]<<"
    ";
      return 0;
    }
    

      

  • 相关阅读:
    (原)Lazarus 异构平台下多层架构思路、DataSet转换核心代码
    (学)新版动态表单研发,阶段成果3
    (学) 如何将 Oracle 序列 重置 清零 How to reset an Oracle sequence
    (学)XtraReport WebService Print 报错
    (原)三星 i6410 刷机 短信 无法 保存 解决 办法
    (原) Devexpress 汉化包 制作工具、测试程序
    linux下网络配置
    apache自带ab.exe小工具使用小结
    Yii::app()用法小结
    PDO使用小结
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7502127.html
Copyright © 2011-2022 走看看