• 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;
    }
    

      

  • 相关阅读:
    乘电梯(动规+单调队列队头优化)
    贪心基础题目整理
    动规基础方程整理
    [第一波模拟day3T3]{益智游戏}(game.cpp)
    [第一波模拟day3T2]{独立集}(bubble.cpp)
    [第一波模拟day1T2]{分班}(divide.cpp)
    考前模版整理
    [Noip2004][Day ?][T?]合并果子(?.cpp)
    [Noip2017][Day 1][T1]玩具谜题(toy.cpp)
    新开始?
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7502127.html
Copyright © 2020-2023  润新知