• Melancholy(磨懒虫主义)


    题目大意:给出n个地点和q个询问。其中每个地点有距离和权值,每个询问给出l,r,k,表示在[l,r]区间内不取最小点的情况下任取k个,求所有情况权值之积之和(n,q<=1e5,k<=6)。

    能看出来是区间操作,先考虑树状数组,发现维护比较难。于是用线段树维护。

    每个节点记录7个值,分别为minv和不算minv任取1~6个所得值。dalao的正解用了RMQ+容斥,但我都没用。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ui unsigned int
    int n,Q;
    struct pla
    {
        int d,v;
    }p[N];
    bool cmp(pla a,pla b)
    {
        return a.d<b.d;
    }
    struct segtree
    {
        ui mn;
        ui v[8];
    }tr[4*N];
    segtree operator * (segtree s0,segtree s1)
    {
        segtree ret;
        for(int i=1;i<=6;i++)
        {
            ret.v[i]=s0.v[i]+s1.v[i];
            for(int j=1;j<i;j++)ret.v[i]+=s0.v[j]*s1.v[i-j];
        }
        ret.mn = min(s0.mn,s1.mn);
        ui mx = max(s0.mn,s1.mn);
        for(int i=6;i>=2;i--)
        {
            ret.v[i]+=ret.v[i-1]*mx;
        }
        ret.v[1]+=mx;
        return ret;
    }
    void update(int u)
    {
        tr[u] = tr[u<<1] * tr[u<<1|1];
    }
    void build(int l,int r,int u)
    {
        if(l==r)
        {
            tr[u].mn=(ui)p[l].v;
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,u<<1);
        build(mid+1,r,u<<1|1);
        update(u);
    }
    segtree query(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return tr[u];
        int mid = (l+r)>>1;
        if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
        else if(qr<=mid) return query(l,mid,u<<1,ql,qr);
        else
        {
            segtree s0=query(l,mid,u<<1,ql,mid);
            segtree s1=query(mid+1,r,u<<1|1,mid+1,qr);
            segtree ret = s0 * s1;
            return ret;
        }
    }
    ui jc[8];
    int mi[24];
    int findl(int d)
    {
        int a = n;
        for(int i=20;i>=0;i--)
        {
            if(a-mi[i]<=0)continue;
            if(p[a-mi[i]].d>=d)a-=mi[i];
        }
        return a;
    }
    int findr(int d)
    {
        int a = 1;
        for(int i=20;i>=0;i--)
        {
            if(a+mi[i]>n)continue;
            if(p[a+mi[i]].d<=d)a+=mi[i];
        }
        return a;
    }
    int main()
    {
    //    freopen("c.in","r",stdin);
    //    freopen("c.out","w",stdout);
        scanf("%d%d",&n,&Q);
        jc[1]=1,jc[2]=2,jc[3]=6,jc[4]=24,jc[5]=120,jc[6]=720;
        mi[0]=1;
        for(int i=1;i<=20;i++)mi[i]=mi[i-1]<<1;
        for(int i=1;i<=n;i++)scanf("%d",&p[i].d);
        for(int i=1;i<=n;i++)scanf("%d",&p[i].v);
        sort(p+1,p+1+n,cmp);
        build(1,n,1);
        for(int ll,rr,l,r,k,i=1;i<=Q;i++)
        {
            scanf("%d%d%d",&ll,&rr,&k);
            l = findl(ll);
            r = findr(rr);
            if(l>r)
            {
                printf("0
    ");
                continue;
            }
            segtree ans;
            ans = query(1,n,1,l,r);
            printf("%u
    ",ans.v[k]*jc[k]);
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    Postman自动化传参实操
    sql语句大全(详细)
    selenium自动化测试-处理iframe
    selenium切换窗口
    selenium中三大窗口切换
    第一个Appium脚本
    Capability配置简介
    APP专项
    Appium环境搭建
    转载——Python Selenium 常用方法总结
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9580598.html
Copyright © 2020-2023  润新知