• BZOJ2809 dispatching


    BZOJ2809 dispatching

    题目传送门

    题解

    这道题目的题解很多,但大多都是用左偏树/主席书做的。这里再介绍一个莫队的做法。首先这题的题目就是在树上选定一个点,然后在这个点的子树中选出一些点,使这些点的(sum c[i])不超过(M),求(Li*)选中点的个数最大。对于选择的部分,我们可以贪心的选择(c)比较小的那部分,使得元素个数最多。然后如果我们暴力枚举每个区间的话,那么时限肯定是不够了,所以我们可以处理出这棵树的(DFS)序,将枚举的每一个区间当做一次询问,然后套用莫队进行转移就行了,是一个比较简单的无修改莫队,复杂度为(O(nsqrt{n}))

    code

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    bool Finish_read;
    template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
    template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
    template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('
    ');}
    template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
    /*================Header Template==============*/
    #define PAUSE printf("Press Enter key to continue..."); fgetc(stdin);
    const int maxn=100010;
    struct edge {
        int nxt,to;
    }E[maxn<<2];
    int blo[maxn];
    struct query {
        int l,r,L;
        bool operator < (const query &rhs) const {
            return blo[l]==blo[rhs.l]?r<rhs.r:blo[l]<blo[rhs.l];
        }
    }q[maxn];
    struct ninja {
        int dfn,cost,l;
        bool operator < (const ninja &rhs) const {
            return cost<rhs.cost;
        }
    }a[maxn];
    int n,cntblock,m,tot,block,cblock,rt,dfnclck;
    int L[maxn],head[maxn],cnt[maxn],sum[maxn],b[maxn],val[maxn],p[maxn];
    /*==================Define Area================*/
     void addedge(int u,int v) {
        E[++tot].to=v;E[tot].nxt=head[u];head[u]=tot;
    }
      
    void dfs(int u) {
        q[u].l=a[u].dfn=++dfnclck;
        for (int i=head[u];~i;i=E[i].nxt) dfs(E[i].to);
        q[u].r=dfnclck;q[u].L=a[u].l;
    }
      
    void Buildblock() {
        cblock=sqrt(dfnclck);
        cntblock=(dfnclck+1)/cblock;
        for(int i=1;i<=dfnclck;i++) blo[i]=(i-1)/cblock+1;
        for(int i=1;i<=cntblock;i++) L[i]=(i-1)*cblock+1;
    }
      
    void Modify(int x,int v) {
        b[x]+=v;
        cnt[blo[x]]+=v;
        sum[blo[x]]+=1ll*v*val[x];
    }
      
    void Getc() {
        dfnclck=0;val[p[a[1].dfn]=++dfnclck]=a[1].cost;
        for (int i=2;i<=n;i++) {
            if(a[i].cost!=a[i-1].cost) dfnclck++;
            val[p[a[i].dfn]=dfnclck]=a[i].cost;
        }
    }
      
    ll Query() {
        ll tot=0;
        ll ans=0;
        for(int i=1;i<=cntblock;i++) {
            tot+=sum[i];ans+=cnt[i];
            if (tot>m) {
                tot-=sum[i];ans-=cnt[i];
                int now=L[i];
                while(1) {
                    tot+=1ll*val[now]*b[now];
                    ans+=b[now];
                    if(tot>m) return ans-(tot-m)/val[now]-((tot-m)%val[now]!=0);
                    now++;
                }
            }
        }
        return ans;
    }
    int main() {
        memset(head,-1,sizeof head);
        read(n);read(m);
        for (int i=1;i<=n;i++) {
            int fa;
            read(fa);read(a[i].cost);read(a[i].l);
            if(!fa) rt=i;
            addedge(fa,i);
        }
        dfnclck=0;
        dfs(rt);
        block=sqrt(n);
        for (int i=1;i<=n;i++) blo[i]=(i-1)/block+1;
        sort(q+1,q+1+n);
        memset(blo,0,sizeof blo);
        sort(a+1,a+1+n);
        Getc();
        Buildblock();
        ll ans=0;
        int l=1,r=0;
        for (int i=1;i<=n;i++) {
            while(r<q[i].r) Modify(p[r+1],1),r++;
            while(r>q[i].r) Modify(p[r],-1),r--;
            while(l<q[i].l) Modify(p[l],-1),l++;
            while(l>q[i].l) Modify(p[l-1],1),l--;
            ans=max(ans,1ll*Query()*q[i].L);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
  • 相关阅读:
    转:超级好用的流程图js框架
    流程图插件
    转:介绍几个著名的实用的Java反编译工具,提供下载
    关于 web.config impersonate 帐号模拟
    SQLSERVER 使用 ROLLUP 汇总数据,实现分组统计,总计(合计),小计
    【论文排版工具】——LaTeX的安装及使用(MiKTeX+TexStudio+Windows)
    C语言输入带空格的字符串
    SQL-连接查询:left join,right join,inner join,full join之间的区别
    MySQL与Oracle的隔离级别
    区块链节点运维相关
  • 原文地址:https://www.cnblogs.com/Apocrypha/p/9434962.html
Copyright © 2020-2023  润新知