首页 > 其他分享 >Atcoder Beginner Contest 376

Atcoder Beginner Contest 376

时间:2024-10-20 11:59:18浏览次数:1  
标签:Atcoder return Beginner 200001 int 376 id dp dis

新猫
     Λ   Λ__
  /(*゚ー゚)/\
 /|  ̄U U ̄|\/
   |      |/

A.Candy Button \(\text{diff } 19\)

你按一次按钮就会得到一颗糖,如果这次按按钮和上次得到糖的间隔时间小于 \(C\) 则不会得到糖,给你若干按按钮的时间,问能得到多少糖

int n,c;
int a[1000001];
signed main(){
    cin>>n>>c;
    int tot=0;
    int last=-1;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        if(last==-1 or a[i]-last>=c){
            tot++;
            last=a[i];
        }
    }
    cout<<tot<<endl;
}

B.Hands on Ring(Easy) \(\text{diff } 290\)

一个环上有 \(N\) 段,初始时左手在 \(1\),右手在 \(2\),手可以每次任意方向移动一步,但是左右手不能重叠,给你若干个操作,表示将一只手移到 \(p_i\)(另一只手不能动)的最小步数

罕见的把史放 T2 的 ABC

我选择分别对两个方向 dfs 一遍

int n,q;
int l=1,r=2;
inline int fixed(int x){
    while(x<1) x+=n;
    while(x>n) x-=n;
    return x;
}
int dfs(int now,bool isadd,bool isl,int step,int goal){
    if((isl and now==r) or (isl==false and now==l)) return 0x7fffffff;
    if(now==goal) return step;
    return dfs(fixed(now+(isadd?1:-1)),isadd,isl,step+1,goal);
}
char getch(){
    char ch=getchar();
    while(!(ch=='L' or ch=='R')) ch=getchar();
    return ch;
}
long long ans=0;
signed main(){
    cin>>n>>q;
    for(int i=1;i<=q;++i){
        char c=getch();int x;cin>>x;
        if(c=='L'){
            ans+=min(dfs(l,true,true,0,x),dfs(l,false,true,0,x));
            l=x;
        }
        else{
            ans+=min(dfs(r,true,false,0,x),dfs(r,false,false,0,x));
            r=x;
        }
    }
    cout<<ans<<endl;
}

C.Prepare Another Box \(\text{diff } 366\)

给你若干物品和盒子及其大小,一个盒子只能装一个大小不超过盒子大小的物品,并且你可以买若干个任意容量的盒子,问是否有办法使得所有玩具都装在盒子里,并且没有剩余的盒子,如果有,输出其最小花费

贪心地想,将所有容量从大到小排序,开双指针,如果能放就放,否则直接买,最后判断盒子是否用完即可

int n;
int a[1000001],b[1000001];
signed main(){
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    for(int i=1;i<=n-1;++i){
        cin>>b[i];
    }
    sort(a+1,a+n+1,[](int x,int y){return x>y;});
    sort(b+1,b+n,[](int x,int y){return x>y;});
    int i=1,j=1,ans=0;
    while(i<=n){
        if(j>n-1){
            ans+=a[i];i++;
            continue;
        }
        if(a[i]<=b[j]){
            i++;j++;
            continue;
        }
        ans+=a[i];i++;
    }
    cout<<(j==n?ans:-1)<<endl;
}

D.Cycle \(\text{diff } 743\)

给定有向图,寻找包含 \(1\) 的最小环

\(N\le 2\times 10^5\)

好题

比较考察对 dij 的理解,包含 \(1\) 的最小环,可以看成找一条从 \(1\) 到 \(1\) 的最短路

一般来说我们干这个的时候都是枚举起始点相邻的点,尝试断开连边跑最短路

但是可以发现,如果我们一开始将 \(dis_1\) 设为 \(inf\),然后对 \(1\) 跑最短路,也能有这个效果

那么你显然就不能用 \(dis_1\) 去做一开始的松弛了,否则你什么也松弛不到,因此你可以往优先队列里放一个 \(dis_1=0\),然后每次拿出优先队列里的值来松弛其他节点,这样也能做到断边的效果

#define int long long
int n,m;
vector<int>e[200001];
int dis[200001];
bool vis[200001];
struct node{
    int id,dis;
    bool operator <(const node&A)const{
        return dis>A.dis;
    }
};
priority_queue<node>q;
void dij(int s){
    memset(dis,0x3f,sizeof dis);
    q.push({s,0});
    while(!q.empty()){
        node u=q.top();q.pop();
        if(vis[u.id]) continue;
        vis[u.id]=true;
        for(int i:e[u.id]){
            if(dis[i]>u.dis+1){
                dis[i]=u.dis+1;
                q.push({i,dis[i]});
            }
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;++i){
        int x,y;cin>>x>>y;
        e[x].push_back(y);
    }
    dij(1);
    cout<<(dis[1]>=0x3f3f3f3f3f?-1:dis[1])<<endl;
}

E.Max×Sum \(\text{diff } 1063\)

给定两个长为 \(N\) 的数列 \(A,B\),从 \(N\) 中选 \(K\) 个数,最小化 \(\max\{A_i\}\times \sum\{B_i\}\) 的值

枚举 \(A_i\),钦定当前的 \(A_i\) 是最大值

就变成了从 \(A_j\) 不超过 \(A_i\) 的 \(j\) 里求 \(b_j\) 的最小值

如果我们从小到大枚举 \(A_i\),则动态地每次维护 \(b_j\) 前 \(K\) 小之和即可

可以用优先队列实现

#define int long long
int n,k;
int id[200001];
int a[200001],b[2000001];
priority_queue<int>q;
signed main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        int ans=0x7fffffffffffffff;
        while(!q.empty()) q.pop();
        cin>>n>>k;
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        for(int i=1;i<=n;++i){
            cin>>b[i];
        }
        iota(id+1,id+n+1,1);
        sort(id+1,id+n+1,[](int x,int y){return a[x]<a[y];});
        int tmp=0;
        for(int i=1;i<=n;++i){
            if(q.size()<k){
                tmp+=b[id[i]];q.push(b[id[i]]);
            }
            else if(q.top()>b[id[i]]){
                tmp+=b[id[i]]-q.top();
                q.pop();q.push(b[id[i]]);
            }
            if((int)q.size()<k) continue;
            ans=min(ans,a[id[i]]*tmp);
        }
        cout<<ans<<'\n';
    }
}

F.Hands on Ring(Hard) \(\text{diff } 2089\)

考虑 DP 实现

可以 DP 是因为,前一个操作已经帮我们确定了一个手的位置,因此我们可以设 \(f_{i,j}\) 表示进行到操作 \(i\) 的时候,另一只手的位置为 \(j\)

转移很水,直接分讨挪左手右手就行了,但是这个题的转移比 B 题沟史十倍

滚动数组压一下,或者直接压成一维也行

#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int n,q;
int dp[200001];
int old[200001];
void f(int s,int g,int x,int cnt){
	//从 s 到 g 的转移(cnt=f_{i-1})
	g=(g-s+n)%n;
	x=(x-s+n)%n;
	for(int j=0;j<2;++j){
		if(x<=g){
			int nt=(g+1)%n;
			if(j==1) nt=n-nt;
			dp[(nt+s)%n]=min(dp[(nt+s)%n],cnt+g+g+1-x);
		}
		else{
			int nt=x;
			if(j==1) nt=n-nt;
			dp[(nt+s)%n]=min(dp[(nt+s)%n],cnt+g);
		}
		g=n-g;
		x=n-x;
	}
};
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>q;
	char lh='L';int lt=0;
	memset(dp,0x3f,sizeof dp);
	dp[1]=0;
	while(q--){
		char h;int t;
		cin>>h>>t;
		t--;
		swap(dp,old);
		memset(dp,0x3f,sizeof dp);
		for(int i=0;i<n;++i){
			if(old[i]!=inf){
				if(h==lh){
					f(lt,t,i,old[i]);
				}
				else{
					f(i,t,lt,old[i]);
				}
			}
		}
		lh=h;lt=t;
	}
	int ans=inf;
	for(int i=0;i<n;++i) ans=min(ans,dp[i]);
	cout<<ans<<endl;
}

标签:Atcoder,return,Beginner,200001,int,376,id,dp,dis
From: https://www.cnblogs.com/HaneDaCafe/p/18486998

相关文章

  • AtCoder Beginner Contest 376
    AtCoderBeginnerContest376\(A\)CandyButton贪心,模拟。点击查看代码intmain(){lln,c,x,last=-0x3f3f3f3f,ans=0,i;cin>>n>>c;for(i=1;i<=n;i++){cin>>x;if(x-last>=c){last=x;......
  • [ABC376E] Max × Sum 题解
    [ABC376E]Max×Sum题解原题链接洛谷链接一道简单的推性质题,首先明确一个性质,子集是非连续的,所以在计算时并不用连续区间求。拿过题来,首先想的是枚举\(B\)的最小子集,但其复杂度为\(O(C_N^K)\)复杂度过高,不足以通过本题。于是转变思路,枚举\(A\)之中的最大值。若\(a_i......
  • AtCoder Beginner Contest 371 - VP记录
    总体发挥还算正常A-Jiro呵呵呵,有人像我这么做的吗?点击查看代码#include<cstdio>usingnamespacestd;intmain(){ charab,ac,bc; scanf("%c%c%c",&ab,&ac,&bc); if(ab=='<'&&ac=='<'&&bc=='<')......
  • C - Word Ladder (Toyota Programming Contest 2024#9 (AtCoder Beginner Contest 370)
    题目链接:C-WordLadder题目:样例:分析:不要被题目所吓到,一切长题目都是纸老虎。题目大意就是给你两个字符串s和t,一次只能更换一个字母,求s变到t更换的次数,并输出每次更换一个字母后的最小字典序字符串。题意好理解,可以直接暴力,大力出奇迹。但是有没有更好的方法呢?既然问了......
  • 358G AtCoder Tour
    358G思维题#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intn,m,s,t,vis[55][55][2505],k;lldis[55][55][2505],v[55][55],ans;intmvx[]={-1,1,0,0};intmvy[]={0,0,-1,1};structNode{intx,y,d;};queue<Node>q;void......
  • 浏览器安装 AtCoder Better 和 Codeforces Better 插件
    你首先需要篡改猴。如果你用的Google浏览器,请用这个Link,不过你可能需要挂个梯子。如果你用的Firefox浏览器,请用这个Link,这个不需要梯子。如果你用的edge浏览器,请用这个Link,这个也不需要梯子。下载好篡改猴之后,无论什么浏览器,点击这个链接,安装AtCoderBetter插件;点......
  • AtCoder ABCD做题计划
    vjudge链接AtCoderBeginnerContest360ABCDAtCoderBeginnerContest359ABCDAtCoderBeginnerContest358ABCDAtCoderBeginnerContest357ABCDAtCoderBeginnerContest356ABCDAtCoderBeginnerContest355ABCDAtCoderBegi......
  • AtCoder Beginner Contest 374 (A-E)
    AtCoderBeginnerContest374(A-E)比赛链接A-Takahashisan2#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidShowball(){strings;cin>>s;intn=s.size();cout<<(s.substr(n-3)=="san"......
  • 代码随想录算法训练营第三十一天|455.分发饼干 376. 摆动序列 53. 最大子序和
    455.分发饼干假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干j,都有一个尺寸s[j] 。如果s[j] >=g[i],我们可以将这个饼干j分配给孩子i,......
  • AtCoder Beginner Contest 375
    A-Seats#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;#defineintlonglongusingvi=vector<int>;usingpii=pair<int,int>;i32main(){ios::sync_with_stdio(false),cin.tie(null......