标签: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 个询问。
10 5 2 3 7 9 5 1 3 10 6 8 2 4 1 7 1 9 1 3 5 9 1 5
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 #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
标签:can 答案 blog blank 一段 problem cin 理解 ++
原文地址:http://www.cnblogs.com/Y-E-T-I/p/7628680.html