• 2020浙江省省赛 B


    传送门

    题意

    输入n,k分别表示n个a[i]体积物品,箱子最大容量为k,求第一种操作和第二种操作需要多少个箱子。

    有两种操作,第一种操作是从1~i-1之间有没有可以放下第i个物体体积的箱子,箱子编号越前面越好

    第二种操作1~i-1之间有没有可以放下第i个物体体积的箱子,使得箱子数最少。

    思路

    第二种操作很好想直接lower_bound的找1~i-1放的箱子(排好序从小到大)寻找合适的,没有合适就再整个箱子。multiset和map都可以用

    然后比赛因为A题卡死,写了4半小时(害,带着队友一起脑淤血)导致最后半小时开B题思路混乱,根本没想到线段树可以nlgn查询,我甚至怀疑队友读错题了……

    赛后想了一个build 建1~n 容量存k-a[i]的树,然后查询第i个是否有大于a[i]的值,如果有删掉第i位置的k-a[i],再去那个符合的位置减去a[i],如果没有就continue

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define rson(x) x<<1
    #define lson(x) x<<1|1
    const int N=1e6+10;
    int po[N],a[N],tree[N<<2],wei[N<<2];
    int n,k,cnt1,cnt2;
    void build(int l,int r,int x){
        if(l==r){
            tree[x]=k-a[l];
            wei[x]=l;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rson(x));
        build(mid+1,r,lson(x));
        tree[x]=max(tree[rson(x)],tree[lson(x)]);
        if(tree[rson(x)]>=tree[lson(x)]){
            wei[x]=wei[rson(x)];
        }
        else{
            wei[x]=wei[lson(x)];
        }
        return ;
    }
    int pp;
    void query(int l,int r,int x,int pos,int zhi){
        if(zhi<=tree[x] && wei[x]<pos){
            pp=min(pp,wei[x]);
        }
        if(l==r || pp<wei[x] || zhi>tree[x]){return;}
        int mid=(l+r)>>1;
        if(tree[rson(x)]>=zhi){
            query(l,mid,rson(x),pos,zhi);
        }
        else if(tree[lson(x)]>=zhi){
            query(mid+1,r,lson(x),pos,zhi);
        }
    }
    void xiugai(int l,int r,int x,int pos,int zhi){
        if(l==pos &&r==pos){
            tree[x]-=zhi;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid){
            xiugai(l,mid,rson(x),pos,zhi);
        }
        if(pos>mid){
            xiugai(mid+1,r,lson(x),pos,zhi);
        }
        tree[x]=max(tree[rson(x)],tree[lson(x)]);
        if(tree[rson(x)]>=tree[lson(x)]){
            wei[x]=wei[rson(x)];
        }
        else{
            wei[x]=wei[lson(x)];
        }
        return ;
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&k);
            cnt1=n,cnt2=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            build(1,n,1);
            for(int i=2;i<=n;i++){
                pp=n+2;
                query(1,n,1,i,a[i]);
                if(pp!=n+2){
                    cnt1--;
                    xiugai(1,n,1,pp,a[i]);
                    xiugai(1,n,1,i,k-a[i]);
                }
            }
            map<int,int>mp;
            map<int,int>::iterator it;
            mp[k]=n;
            for(int i=1;i<=n;i++){
                it=mp.lower_bound(a[i]);
                int zhi=it->first;
                mp[zhi]--;mp[zhi-a[i]]++;
                if(mp[zhi]==0){
                    mp.erase(it);
                }
            }
            for(auto i:mp){
                if(i.first==k){continue;}
                cnt2+=i.second;
            }
            printf("%d %d
    ",cnt1,cnt2);
        }
        return 0;
    }
    
    

    水哥的猛思路

    哎,如果没有疫情水哥估计银冲金了,而我三题打铁了,E题主席树赛后补题也卡死,比赛结论都没去想,c题题目都没读……

    水哥思路直接建1~n全是k的,然后找到k就cnt1++,就好了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define lson(x) x<<1
    #define rson(x) x<<1|1
    const int N=1e6+10;
    int po[N],sum[N],a[N],tree[N<<2],wei[N<<2];
    int n,k,cnt1,cnt2;
    void build(int l,int r,int x){
        if(l==r){
            tree[x]=k;return;
        }
        int mid=(l+r)>>1;
        build(l,mid,lson(x));
        build(mid+1,r,rson(x));
        tree[x]=max(tree[rson(x)],tree[lson(x)]);
        return ;
    }
    void xiugai(int l,int r,int x,int zhi){
        if(l==r){
            if(tree[x]==k)cnt1++;
            if(tree[x]>=zhi)tree[x]-=zhi;
            return ;
        }
        int mid=(l+r)>>1;
        if(tree[lson(x)]>=zhi){
            xiugai(l,mid,lson(x),zhi);
        }
        else if(tree[rson(x)]>=zhi){
            xiugai(mid+1,r,rson(x),zhi);
        }
        tree[x]=max(tree[rson(x)],tree[lson(x)]);
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&k);
            cnt1=0,cnt2=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            build(1,n,1);
            for(int i=1;i<=n;i++){
                xiugai(1,n,1,a[i]);
            }
            map<int,int>mp;
            map<int,int>::iterator it;
            mp[k]=n;
            for(int i=1;i<=n;i++){
                it=mp.lower_bound(a[i]);
                int zhi=it->first;
                mp[zhi]--;mp[zhi-a[i]]++;
                if(mp[zhi]==0){
                    mp.erase(it);
                }
            }
            for(auto i:mp){
                if(i.first==k){continue;}
                cnt2+=i.second;
            }
            printf("%d %d
    ",cnt1,cnt2);
        }
        return 0;
    }
    

    orz

    虽然补题到了五题,E题也抄模板过了,但好难受,比赛的时候可能策略出错了吧脑子也不够清醒,说到底还是菜,希望能变强吧

  • 相关阅读:
    Mysql一分钟定位 Next-Key Lock,你需要几分钟
    golang 服务大量 CLOSE_WAIT 故障排查
    Mysql大并发热点行更新的两个骚操作
    golang 服务诡异499、504网络故障排查
    golang 服务平滑重启小结
    vim 列编辑模式
    特邀全球互联网技术大会(麒麟会GITC)分享 —大型团购系统架构设计
    ElasticSearch 评分排序
    zookeeper 实现分布式锁安全用法
    诡异的druid链接池链接断开故障经验总结
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/13851713.html
Copyright © 2020-2023  润新知