【题目简述】
DX3906星系,Melancholy星上,我在勘测这里的地质情况。
我把这些天来已探测到的区域分为N组,并用二元组(D,V)对每一组迚行标记:其中D为区域的相对距离,V为内部地质元素的相对丰富程度。
在我的日程安排表上有Q项指派的计划。每项计划的形式是类似的,都是“对相对距离D在[L,R]乊间的区域迚行迚一步的勘测,并在其中有次序地挑出K块区域的样本迚行研究。”采集这K块的样品后,接下来在实验中,它们的研究价值即为这K块区域地质相对丰富程度V的乘积。
我对这Q项计划都迚行了评估:一项计划的评估值P为所有可能选取情况的研究价值乊和。
但是由于仪器的原因,在一次勘测中,这其中V最小的区域永进丌会被选取。
现在我只想知道这Q项计划的评估值对2^32取模后的值,特殊地,如果没有K块区域可供选择,评估值为0。
【输入格式】
第一行给出两个整数,区域数N不计划数Q。
第二行给出N个整数,代表每一块区域的相对距离D。
第三行给出N个整数,代表每一块区域的内部地质元素的相对丰富程度V。
接下来的Q行,每一行3个整数,代表相对距离的限制L,R,以及选取的块数K。
【输出格式】
输出包括Q行,每一行一个整数,代表这项计划的评估值对2^32取模后的值。
【数据范围】
N,Q<=10^5
D,V,L,R<=10^9
K<=6
-------------------------------华丽的分割线-------------------------------------------------
维护区间的卷积,考虑用线段树。。。
根据卷积的计算公式(c[x]=a[0]b[x]+a[1]b[x-1]+a[2]b[x-2]+......)维护线段树
#include<cstdio> #include<cstring> #include<algorithm> #define uint unsigned int using namespace std; int n,m,cnt,tot,q,ql,qr,l,r,k; uint mul[7]={0,1,2,6,24,120,720}; struct node{ int d; int v; }pl[100005]; struct Tree{ int minn; int maxn; uint sum[7]; }tr[100000*5+5]; int cmp(node a,node b){ return a.d<b.d; } int check(int p){ int L=1,R=n; while(L<=R){ int mid=(L+R)>>1; if(pl[mid].d<p)L=mid+1; else R=mid-1; } return L; } void update1(int o){ tr[o].minn=min(tr[o*2].minn,tr[o*2+1].minn); tr[o].maxn=max(tr[o*2].minn,tr[o*2+1].minn); tr[o].sum[0]=1; for(int i=1;i<=6;i++){ for(int j=0;j<=i;j++){ tr[o].sum[i]+=tr[o*2].sum[j]*tr[o*2+1].sum[i-j]; } } for(int i=6;i>=1;i--){ tr[o].sum[i]+=tr[o].maxn*tr[o].sum[i-1]; } } Tree update2(Tree a,Tree b){ Tree ret; memset(ret.sum,0,sizeof(ret.sum)); ret.sum[0]=1; ret.minn=min(a.minn,b.minn); ret.maxn=max(a.minn,b.minn); for(int i=1;i<=6;i++){ for(int j=0;j<=i;j++){ ret.sum[i]+=a.sum[j]*b.sum[i-j]; } } for(int i=6;i>=1;i--){ ret.sum[i]+=ret.maxn*ret.sum[i-1]; } return ret; } void build(int o,int l,int r){ if(l==r){ tr[o].minn=pl[l].v; tr[o].sum[0]=1; return; } int mid=(l+r)>>1; build(o*2,l,mid); build(o*2+1,mid+1,r); update1(o); } Tree query(int o,int l,int r,int L,int R){ if(l>=L&&r<=R){ return tr[o]; } int mid=(l+r)>>1; if(mid>=R){ return query(o*2,l,mid,L,R); } else if(mid<L){ return query(o*2+1,mid+1,r,L,R); } else{ Tree ls=query(o*2,l,mid,L,mid); Tree rs=query(o*2+1,mid+1,r,mid+1,R); return update2(ls,rs); } } int main(){ //freopen("c.in","r",stdin); //freopen("c.out","w",stdout); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ scanf("%d",&pl[i].d); } for(int i=1;i<=n;i++){ scanf("%d",&pl[i].v); } sort(pl+1,pl+n+1,cmp); build(1,1,n); for(int i=1;i<=q;i++){ scanf("%d%d%d",&l,&r,&k); ql=check(l); qr=check(r); if(pl[qr].d>r)qr--; if(qr<ql){ printf("0 "); continue; } Tree ans=query(1,1,n,ql,qr); printf("%u ",ans.sum[k]*mul[k]); } return 0; }