码迷,mamicode.com
首页 > 其他好文 > 详细

[AH/HNOI2017]影魔

时间:2017-10-05 11:01:26      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:can   答案   blog   blank   一段   problem   cin   理解   ++   

题目背景

影魔,奈文摩尔,据说有着一个诗人的灵魂。 事实上,他吞噬的诗人灵魂早已成千上万。

千百年来,他收集了各式各样的灵魂,包括诗人、 牧师、 帝王、 乞丐、 奴隶、 罪人,当然,还有英雄。

题目描述

每一个灵魂,都有着自己的战斗力,而影魔,靠这些战斗力提升自己的攻击。

奈文摩尔有 n 个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号 1 到 n。第 i个灵魂的战斗力为 k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对 i, j(i<j)来说,若不存在 ks大 于 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]。

输入输出格式

输入格式:

输入文件名为 sf.in。

第一行 n,m,p1,p2

第二行 n 个数: k[1],k[2],…,k[n]

接下来 m 行, 每行两个数 a,b, 表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。

输出格式:

输出文件名为 sf.out

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

输入输出样例

输入样例#1:
10 5 2 3
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5
输出样例#1:
30
39
4
13
16

说明

30%: 1<= n,m <= 500。

另 30%: p1=2*p2。

100%:1 <= n,m <= 200000; 1 <= p1,p2 <= 1000。

令L[i]为i前第一个比a[i]大的一位,R[i]为i后第一个比a[i]大的一位

1.每组(i,L[i]) (R[i],i) (i,i+1)可以贡献p1
2.(L[i],j) (i+1<=j<=R[i]-1)  (j,R[i])(L[i]+1<=j<=i-1) 都可以贡献p2
然后就是统计:
我们假设i和[i+1,R[i]-1]之间的数都可以搭配成p2的条件,然后我们就在线段树中把[i+1,R[i]-1]加上p2.
因为(i,R[i])在反方向算作了p2,所以应该+p1-p2,这样反向算时等价于只+p1
对于i和L[i],把数列和询问反转,在做一次相同操作
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 struct Ask
  7 {
  8     int l,r,id;
  9 }q[200001];
 10 int a[200001],aa[200001],n,m,stack[200001],R[200001];
 11 long long c[800001],mark[800001],ans[200001],p1,p2;
 12 bool cmp(Ask a,Ask b)
 13 {
 14     return a.l<b.l;
 15 }
 16 void pushup(int rt)
 17 {
 18     c[rt]=c[rt*2]+c[rt*2+1];
 19 }
 20 void pushdown(int rt,int l,int r,int mid)
 21 {
 22     if (mark[rt])
 23     {
 24         mark[rt*2]+=mark[rt];
 25         mark[rt*2+1]+=mark[rt];
 26         c[rt*2]+=mark[rt]*(mid-l+1);
 27         c[rt*2+1]+=mark[rt]*(r-mid);
 28         mark[rt]=0;
 29     }
 30 }
 31 void change(int rt,int l,int r,int L,int R,long long d)
 32 {
 33     if (l>=L&&r<=R)
 34     {
 35         mark[rt]+=d;
 36         c[rt]+=(r-l+1)*d;
 37         return;
 38     }
 39     pushdown(rt,l,r,(l+r)/2);
 40     int mid=(l+r)/2;
 41     if (L<=mid) change(rt*2,l,mid,L,R,d);
 42     if (R>mid) change(rt*2+1,mid+1,r,L,R,d);
 43     pushup(rt); 
 44 }
 45 long long getsum(int rt,int l,int r,int L,int R)
 46 {
 47     if (l>=L&&r<=R)
 48     {
 49         return c[rt];
 50     }
 51     int mid=(l+r)/2;
 52     pushdown(rt,l,r,mid);
 53     long long s=0;
 54     if (L<=mid) s+=getsum(rt*2,l,mid,L,R);
 55     if (R>mid) s+=getsum(rt*2+1,mid+1,r,L,R);
 56     pushup(rt);
 57     return s;
 58 }
 59 void work()
 60 {int i;
 61 memset(c,0,sizeof(c));
 62 memset(mark,0,sizeof(mark));
 63     sort(q+1,q+m+1,cmp);
 64     int top=0;
 65     stack[0]=n+1;
 66     for (i=n;i>=1;i--)
 67     {
 68         while (top&&a[i]>=a[stack[top]]) top--;
 69         R[i]=stack[top];
 70         stack[++top]=i;
 71     }
 72     top=m;
 73     for (i=n;i>=1;i--)
 74     {
 75         if (i+1<=R[i]-1)
 76         change(1,1,n,i+1,R[i]-1,p2);
 77         change(1,1,n,R[i],R[i],p1-p2);
 78         while (top&&q[top].l==i) 
 79         ans[q[top].id]+=getsum(1,1,n,1,q[top].r),top--;
 80     }
 81 }
 82 void rev()
 83 {int i;
 84     for (i=1;i<=n;i++)
 85     aa[i]=a[n-i+1];
 86     for (i=1;i<=n;i++)
 87     a[i]=aa[i];
 88 }
 89 int main()
 90 {int i;
 91     cin>>n>>m>>p1>>p2;
 92     for (i=1;i<=n;i++)
 93     {
 94         scanf("%d",&a[i]);
 95     }
 96     for (i=1;i<=m;i++)
 97     {
 98         scanf("%d%d",&q[i].l,&q[i].r);
 99         q[i].id=i; 
100     }
101     work();
102     rev();
103     for (i=1;i<=m;i++)
104     q[i].l=n+1-q[i].l,q[i].r=n+1-q[i].r,swap(q[i].l,q[i].r);
105     work();
106     for (i=1;i<=m;i++)
107     printf("%lld\n",ans[i]);
108 }

庆祝FGO第一/二个SSR

[AH/HNOI2017]影魔

标签:can   答案   blog   blank   一段   problem   cin   理解   ++   

原文地址:http://www.cnblogs.com/Y-E-T-I/p/7628680.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!