Description
DX3906星系,Melancholy星上,我在勘测这里的地质情况。
我把这些天来已探测到的区域分为N组,并用二元组(D,V)对每一组进行标记:其中D为区域的相对距离,V为内部地质元素的相对丰富程度。
在我的日程安排表上有Q项指派的计划。每项计划的形式是类似的,都是“对相对距离D在[L,R]之间的区域进行进一步的勘测,并在其中有次序地挑出K块区域的样本进行研究。”采集这K块的样品后,接下来在实验中,它们的研究价值即为这K块区域地质相对丰富程度V的乘积。
我对这Q项计划都进行了评估:一项计划的评估值P为所有可能选取情况的研究价值之和。
但是由于仪器的原因,在一次勘测中,这其中V最小的区域永远不会被选取。
现在我只想知道这Q项计划的评估值对2^32取模后的值,特殊地,如果没有K块区域可供选择,评估值为0。
Input
第一行给出两个整数,区域数N与计划数Q。
第二行给出N个整数,代表每一块区域的相对距离D。
第三行给出N个整数,代表每一块区域的内部地质元素的相对丰富程度V。
接下来的Q行,每一行3个整数,代表相对距离的限制L,R,以及选取的块数K。
Output
输出包括Q行,每一行一个整数,代表这项计划的评估值对2^32取模后的值。
Sample Input
5 3
5 4 7 2 6
1 4 5 3 2
6 7 1
2 6 2
1 8 3
Sample Output
5
52
924
Data Constraint
思路
发现k不大,而且是个区间问题,不妨考虑线段树。
线段树维护区间最小值和区间k=1…6的答案
合并时f[k]=f[i]*f[k-j]
代码
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef unsigned int u32;
const int maxn=1000005;
const u32 inf=4294967295u;
int n,q;
int k;
struct node
{
u32 d,v;
}a[maxn],L,R;
bool cmp(const node &a,const node &b) {return a.d < b.d;}
struct power
{
u32 val[7];
friend power operator +(power a,power b)
{
power c;
for(int i=1; i<=6; i++) c.val[i]=a.val[i]+b.val[i];
for(int i=1; i<=6; i++)
for(int j=1; j < i; j++)
c.val[i] += a.val[j]*b.val[i-j];
return c;
}
}Node[maxn],A[3],Ans;
struct Min
{
u32 val,pos;
friend Min operator +(Min a,Min b)
{
Min c=(Min){inf,0};
if(a.val < c.val) c=a;
if(b.val < c.val) c=b;
return c;
}
}Val[maxn],res_min;
void build(int i,int l,int r)
{
Val[i]=(Min){inf,0};
for(int j=1; j<=6; j++) Node[i].val[j]=0;
if(l == r)
{
Node[i].val[1]=a[l].v;
Val[i]=(Min){a[l].v,l};
return;
}
int mid=l+r >> 1;
build(i << 1,l,mid); build(i << 1 | 1,mid+1,r);
Node[i]=Node[i << 1]+Node[i << 1 | 1];
Val[i]=Val[i << 1]+Val[i << 1 | 1];
}
void find(int i,int l,int r,int L,int R)
{
if(L>R) return;
if(L<=l&&r<=R)
{
res_min=res_min+Val[i];
return;
}
int mid=l+r >> 1;
if(L<=mid) find(i << 1,l,mid,L,R);
if(mid+1<=R) find(i << 1 | 1,mid+1,r,L,R);
}
void query(int i,int l,int r,int L,int R,int opt)
{
if(L>R) return;
if(L<=l&&r<=R)
{
A[opt]=A[opt]+Node[i];
return;
}
int mid=l+r>>1;
if(L<=mid) query(i<<1,l,mid,L,R,opt);
if(mid+1<=R) query(i<<1|1,mid+1,r,L,R,opt);
}
void solve(int k)
{
int LL=lower_bound(a+1,a+n+1,L,cmp)-a;
int RR=upper_bound(a+1,a+n+1,R,cmp)-a-1;
if(LL>=RR) {printf("0\n"); return;}
res_min=(Min){inf,0};
find(1,1,n,LL,RR);
for(int i=1; i<=6; i++) A[1].val[i]=A[2].val[i]=0;
query(1,1,n,LL,res_min.pos-1,1);
query(1,1,n,res_min.pos+1,RR,2);
Ans=A[1]+A[2];
for(u32 i=1; i<=k; i++) Ans.val[k]*=i;
printf("%u\n",Ans.val[k]);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1; i<=n; i++) scanf("%u",&a[i].d);
for(int i=1; i<=n; i++) scanf("%u",&a[i].v);
sort(a+1,a+n+1,cmp);
build(1,1,n);
while(q--)
{
scanf("%u%u%u",&L.d,&R.d,&k);
solve(k);
}
}