0
点赞
收藏
分享

微信扫一扫

2022/4/30

E_topia 2022-04-30 阅读 78

Sage's Birthday (hard version)

还以为这个难得版本得有多难呢,直接按照常规思路来就可以,n个数最多能有(n-1)/2个cheap,然后将a数组分成两个数组,一个b数组存前(n-1)/2个最小值,一个c数组存剩下的数,然后用二分将最小值不断地插入到c中统计次数输出就行;

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=1e18;
const ll mod=1e9+7;
ll n,a[100005],b[100005],c[100005],vis[100005];
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    sort(a+1,a+n+1);
    if(n==1||n==2){
        printf("0\n");
        for(int i=1;i<=n;i++) printf("%lld ",a[i]);
        return 0;
    }
    ll ans=0,bb=0,cc=0,bou=1;
    for(int i=1;i<=(n-1)/2;i++) b[++bb]=a[i];
    for(int i=(n-1)/2+1;i<=n;i++) c[++cc]=a[i];
    for(int i=1;i<=bb;i++){
        ll id=upper_bound(c+bou,c+cc+1,b[i])-c;
        if(id+1<=cc&&!vis[id]){
            vis[id]=b[i];
            ans++;
            bou=id+1;
        }
        else{
            vis[bou++]=b[i];
        }
    }
    printf("%lld\n",ans);
    for(int i=1;i<=cc;i++){
        printf("%lld ",c[i]);
        if(vis[i]) printf("%lld ",vis[i]);
    }
    ll x=n+1;
    while(vis[x]!=0) printf("%lld ",vis[x]),x++;//这句话貌似没用
	return 0;
}

Constructing the Array

看了得半小时,发现没有啥规律,只能去看一下标签提示,有数据结构就突然想到了优先队列,不得不说优先队列真是个好东西,用优先队列去模拟这个情况就可以了;

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=1e18;
const ll mod=1e9+7;
ll t,n,ans[200005];
struct node{
    ll l,r;
    bool operator<(const node &a)const{
        if(a.r-a.l==r-l) return a.r<r;
        return a.r-a.l>r-l;
    }
};
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%lld",&t);
    while(t--){
        scanf("%lld",&n);
        for(int i=1;i<=n;i++) ans[i]=0;
        priority_queue<node>q;
        q.push(node{1,n});
        ll cnt=1;
        while(!q.empty()){
            node u=q.top();q.pop();
            if((u.r-u.l+1)&1){
                ans[(u.r+u.l)/2]=cnt;
                if((u.l+u.r)/2-1>=u.l) q.push(node{u.l,(u.r+u.l)/2-1});
                if((u.l+u.r)/2+1<=u.r) q.push(node{(u.r+u.l)/2+1,u.r});
            }
            else{
                ans[(u.l+u.r-1)/2]=cnt;
                if((u.l+u.r-1)/2-1>=u.l) q.push(node{u.l,(u.l+u.r-1)/2-1});
                if((u.l+u.r-1)/2+1<=u.r) q.push(node{(u.l+u.r-1)/2+1,u.r});
            }
            cnt++;
        }
        for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
        printf("\n");
    }
	return 0;
}

L-Spicy Restaurant_2021 年第十三届四川省 ACM-ICPC 大学生程序设计竞赛(重现赛)(重现赛) (nowcoder.com)

多源bfs,w的值只有100,所以可以暴力预处理出i点到辣味j的最短距离,dis[j][i]表示i点到辣味j的最短距离,多源bfs跑一下,然后再正着转移一遍,之后判断;

(11条消息) The 2021 Sichuan Provincial 四川省赛 L. Spicy Restaurant(多源bfs)_issue是fw的博客-CSDN博客

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
int cnt,head[200005],dis[110][100005],inf;
int n,m,q,w[100005];
struct Edge{
    int to,dis,next;
}edge[200005];
void addedge(int from,int to){
    edge[++cnt].to=to;
    edge[cnt].next=head[from];
    head[from]=cnt;
}
void bfs(int sp){
    queue<int>q;
    for(int i=1;i<=n;i++)
    if(w[i]==sp){
        q.push(i);
        dis[sp][i]=0;
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=edge[i].next){
            int j=edge[i].to;
            if(dis[sp][j]!=inf) continue;//这地方其实和vis数组的作用一样,但这样省的另开一个了
            //做法也挺巧妙的,也省去了一些思考复杂度
            dis[sp][j]=dis[sp][u]+1;
            q.push(j);
        }
    }
}
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }

    memset(dis,0x3f,sizeof(dis));
    inf=dis[0][0];
    for(int i=100;i>=1;i--) bfs(i);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=100;j++)
        dis[j][i]=min(dis[j][i],dis[j-1][i]);
    while(q--){
        int l,r;
        scanf("%d%d",&l,&r);
        if(dis[r][l]==inf) printf("-1\n");
        else printf("%d\n",dis[r][l]);
    }
	return 0;
}

P1083 [NOIP2012 提高组] 借教室 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

用差分数组去维护前x天的增量,再反推回前x天每天需要多少教室,然后去判断,这个x要去二分得到,为什么可以用二分呢,二分能使用的条件是单调递增或者是局部舍弃性,如果我们第i天满足不了,那后面的也一定满足不了,如果第i天满足了,那么前i-1天也一定能满足,这就符合局部舍弃性,所以可以二分;

 2012 D2 T2 借教室 题解 - 笨蛋花的小窝qwq - 洛谷博客

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=1e18;
const ll mod=1e9+7;
ll n,m,r[1000006],b[1000006],d[1000006],s[1000006],t[1000006],need[1000006];
bool check(ll x){
    memset(b,0,sizeof(b));
    for(int i=1;i<=x;i++){
        b[s[i]]+=d[i];
        b[t[i]+1]-=d[i];
    }
    for(int i=1;i<=n;i++){
        need[i]=need[i-1]+b[i];
        if(need[i]>r[i]) return 0;
    }
    return 1;
}
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&r[i]);
    for(int i=1;i<=m;i++) scanf("%lld%lld%lld",&d[i],&s[i],&t[i]);
    if(check(m)){
        printf("0\n");
        return 0;
    }
    ll l=1,r=m,ans=inf;
    while(l<=r){
        ll mid=l+r>>1;
        if(!check(mid)) ans=min(mid,ans),r=mid-1;
        else l=mid+1;
    }
    printf("-1\n%lld",ans);
	return 0;
}
举报

相关推荐

2022/01/30

2022/4/4

2022-04-30hm

2022/4/9-2022/4/10

2022/4/4偷懒

4-30流--案例

2022/4/13

2022/4/17

0 条评论