磨懒虫主义

【题目简述】
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\n");
            continue;
        }
        Tree ans=query(1,1,n,ql,qr);
        printf("%u\n",ans.sum[k]*mul[k]);
    }
    return 0;
}

 

posted @ 2018-09-04 20:40  Mr_Handsome  阅读(209)  评论(0编辑  收藏  举报