标签:stdin 多少 提升 组成 esc efi print 战斗 pre
正解:主席树+单调栈。
考虑每个点为最大值时能产生的贡献。
设当前点为$p$,左边比$p$大的第一个点为$x$,右边比$p$大的第一个点为$y$,$x$和$y$可以用单调栈求出。
那么只有$(x,y)$能产生$p1$的贡献,$(x,[p+1,y-1])$和$(y,[x+1,p-1])$能产生$p2$的贡献,这可以看成很多点对。
为了方便,我们把$p1$产生贡献的点对分成$(x,y)$和$(y,x)$,$p2*2$。
于是我们找出所有这些点对,把这些点对按照横坐标排序。
然后从前往后建主席树,区间修改+标记永久化即可。
查询的时候直接查询对应区间,即$[a,b]$线段树中的$[a,b]$之和,直接除以$2$,然后再加上$(b-a)*p1$。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (300010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct data{ ll c,p,l,r; }q[4*N]; 24 25 ll sum[40*N],lazy[40*N],ls[40*N],rs[40*N],rt[N],sz; 26 ll lst[N],nxt[N],st[N],k[N],n,m,p1,p2,x,cnt,top; 27 28 il ll gi(){ 29 RG ll x=0,q=1; RG char ch=getchar(); 30 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 31 if (ch==‘-‘) q=-1,ch=getchar(); 32 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 33 return q*x; 34 } 35 36 il ll cmp(const data &a,const data &b){ return a.p<b.p; } 37 38 il void update(RG ll x,RG ll &y,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll v){ 39 lazy[y=++sz]=lazy[x],ls[y]=ls[x],rs[y]=rs[x]; 40 if (xl<=l && r<=xr){ sum[y]=sum[x]+(r-l+1)*v,lazy[y]+=v; return; } 41 RG ll mid=(l+r)>>1; 42 if (xr<=mid) update(ls[x],ls[y],l,mid,xl,xr,v); 43 else if (xl>mid) update(rs[x],rs[y],mid+1,r,xl,xr,v); 44 else update(ls[x],ls[y],l,mid,xl,mid,v),update(rs[x],rs[y],mid+1,r,mid+1,xr,v); 45 sum[y]=sum[ls[y]]+sum[rs[y]]+(r-l+1)*lazy[y]; return; 46 } 47 48 il ll query(RG ll x,RG ll y,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll la){ 49 if (xl<=l && r<=xr) return sum[y]-sum[x]+(r-l+1)*la; 50 RG ll mid=(l+r)>>1; la+=lazy[y]-lazy[x]; 51 if (xr<=mid) return query(ls[x],ls[y],l,mid,xl,xr,la); 52 else if (xl>mid) return query(rs[x],rs[y],mid+1,r,xl,xr,la); 53 else return query(ls[x],ls[y],l,mid,xl,mid,la)+query(rs[x],rs[y],mid+1,r,mid+1,xr,la); 54 } 55 56 il void work(){ 57 n=gi(),m=gi(),p1=gi(),p2=gi(); 58 for (RG ll i=1;i<=n;++i){ 59 k[i]=gi(); 60 while (top && k[st[top]]<k[i]) nxt[st[top--]]=i; 61 lst[i]=st[top],st[++top]=i; 62 } 63 while (top) nxt[st[top--]]=n+1; 64 for (RG ll i=1;i<=n;++i){ 65 if (lst[i] && nxt[i]<=n){ 66 q[++cnt]=(data){1,lst[i],nxt[i],nxt[i]}; 67 q[++cnt]=(data){1,nxt[i],lst[i],lst[i]}; 68 } 69 if (lst[i] && nxt[i]-i>1) 70 q[++cnt]=(data){2,lst[i],i+1,nxt[i]-1}; 71 if (nxt[i]<=n && i-lst[i]>1) 72 q[++cnt]=(data){2,nxt[i],lst[i]+1,i-1}; 73 } 74 sort(q+1,q+cnt+1,cmp); 75 for (RG ll i=1;i<=cnt;++i){ 76 while (x<q[i].p) rt[x+1]=rt[x],++x; 77 update(rt[x],rt[x],1,n,q[i].l,q[i].r,(q[i].c==1 ? p1 : 2*p2)); 78 } 79 while (x<n) rt[x+1]=rt[x],++x; 80 for (RG ll i=1;i<=m;++i){ 81 RG ll a=gi(),b=gi(); 82 printf("%lld\n",query(rt[a-1],rt[b],1,n,a,b,0)/2+(b-a)*p1); 83 } 84 return; 85 } 86 87 int main(){ 88 File("sf"); 89 work(); 90 return 0; 91 }
标签:stdin 多少 提升 组成 esc efi print 战斗 pre
原文地址:http://www.cnblogs.com/wfj2048/p/6784833.html