[线段树][数学]JZOJ 4237 Melancholy
分析
我们离散以后建线段树,然后剔除最小值也很简单,把最小值的位置找出来,求l,pos-1;pos+1,r的值就行了
然后值=∑i=1leftval[i]+right[val][i] +∑i=1i<=6∑j=1j<ileftval[j]*rightval[i-j]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> using namespace std; #define lson t[x].l #define rson t[x].r typedef unsigned int ll; const int N=1e5+10; struct Area { ll d,v; bool operator < (const Area a) const { return d<a.d; } }a[N]; struct Seg { int l,r,pos; ll min,sum[7]; }t[4*N]; int cnt,rt; int tpos; ll tmin,b[2][7],ans[7],l,r; int n,q,k; inline void Build(int &x,int l,int r) { if (!x) x=++cnt; if (l==r) { t[x].min=t[x].sum[1]=a[l].v;t[x].pos=l; return; } register int mid=l+r>>1; Build(lson,l,mid);Build(rson,mid+1,r); t[x].min=min(t[lson].min,t[rson].min); t[x].pos=t[x].min==t[lson].min?t[lson].pos:t[rson].pos; for (register int i=1;i<=6;i++) t[x].sum[i]=t[lson].sum[i]+t[rson].sum[i]; for (register int i=1;i<=6;i++) for (register int j=1;j<i;j++) t[x].sum[i]+=t[lson].sum[j]*t[rson].sum[i-j]; } inline void Get_Min(int x,int l,int r,int xl,int xr) { if (xl<=l&&r<=xr) { if (tmin>t[x].min) tmin=t[x].min,tpos=t[x].pos; return; } register int mid=l+r>>1; if (xl<=mid) Get_Min(lson,l,mid,xl,xr); if (mid<xr) Get_Min(rson,mid+1,r,xl,xr); } inline void Query(int x,int l,int r,int xl,int xr,int side) { if (l>r||l>xr||xl>r||xl>xr) return; if (xl<=l&&r<=xr) { ll c[7]={0,0,0,0,0,0,0}; for (register int i=1;i<=6;i++) c[i]=b[side][i]+t[x].sum[i]; for (register int i=1;i<=6;i++) for (register int j=1;j<i;j++) c[i]+=b[side][j]*t[x].sum[i-j]; memcpy(b[side],c,sizeof c); return; } register int mid=l+r>>1; if (xl<=mid) Query(lson,l,mid,xl,xr,side); if (mid<xr) Query(rson,mid+1,r,xl,xr,side); } inline void Solve() { l=lower_bound(a+1,a+n+1,(Area){l,0})-a; r=upper_bound(a+1,a+n+1,(Area){r,0})-a-1; if (r-l<k) { printf("0\n"); return; } if (l>=r) { printf("0\n"); return; } tmin=2147483647u;tpos=-1; Get_Min(rt,1,n,l,r); memset(b,0,sizeof b); Query(rt,1,n,l,tpos-1,0);Query(rt,1,n,tpos+1,r,1); for (register int i=1;i<=6;i++) ans[i]=b[0][i]+b[1][i]; for (register int i=1;i<=6;i++) for (int j=1;j<i;j++) ans[i]+=b[0][j]*b[1][i-j]; for (register int i=1;i<=k;i++) ans[k]*=i; printf("%u\n",ans[k]); } int main() { scanf("%d%d",&n,&q); for (int i=1;i<=n;i++) scanf("%d",&a[i].d); for (int i=1;i<=n;i++) scanf("%d",&a[i].v); sort(a+1,a+n+1); Build(rt,1,n); for (int i=1;i<=q;i++) { scanf("%d%d%d",&l,&r,&k); Solve(); } }
在日渐沉没的世界里,我发现了你。