码迷,mamicode.com
首页 > 其他好文 > 详细

2020浙江省省赛 B

时间:2020-10-21 21:02:07      阅读:35      评论:0      收藏:0      [点我收藏+]

标签:second   卡死   编号   线段   str   print   表示   操作   --   

题意

输入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\n",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\n",cnt1,cnt2);
    }
    return 0;
}

orz

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

2020浙江省省赛 B

标签:second   卡死   编号   线段   str   print   表示   操作   --   

原文地址:https://www.cnblogs.com/luoyugongxi/p/13851713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!