【Java/补题/平台/ACM赛制】牛客小白月赛56

题目链接

牛客小白月赛56

知识一览

01-贪心
02-线性筛
03-堆优化Dijkstra

题目列表

快输

    static class FastReader{
        BufferedReader br;
        StringTokenizer st;
        String tmp;

        public FastReader() {
            br=new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while(st==null||!st.hasMoreElements()) {
                try {
                    st=new StringTokenizer(br.readLine());
                }catch(IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong(){return Long.parseLong(next());}

        String nextLine() {
            String str="";
            try {
                str=br.readLine();
            }catch(IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        boolean hasNext(){
            if(st!=null&&st.hasMoreTokens())return true;
            try {
                tmp=br.readLine();
                st=new StringTokenizer(tmp);
            }catch(IOException e) {
                return false;
            }
            return true;
        }
    }

    static PrintWriter out=new PrintWriter(
            new BufferedWriter(new OutputStreamWriter(System.out)));
    static FastReader sc=new FastReader();

C 阿宁吃粽子(排序/贪心)

题目描述
阿宁的公司给阿宁发了各种口味的粽子。
一共有 n条粽子,每条粽子有个美味值 ai。
阿宁想立即吃下全部。吃下第 k条粽子时,该粽子的美味值是 x,阿宁获得 2^(k mod 10) ×x 的愉悦值。(k 从 1开始)
阿宁想安排一下吃粽子的顺序,使她获得的愉悦值最大。
输入描述:
第一行输入一个正整数 n。
第二行输入 n 个正整数 ai,ai表示第 i条粽子的美味值。
1≤n,ai ≤2×10^5
输出描述:
一行输出 n 个正整数,第 j 个数表示吃下的第 j 条粽子的美味值。
如果有多解,请把美味值较大的粽子,安排到后面。(好吃的留到后面)
示例1
输入
3
3 1 2
输出
1 2 3
说明
该方案美味值为 1 * 2^1 + 2 * 2^2 + 3 * 2^3 = 34,没有别的方案的愉悦值大于 34。
示例2
输入
12
4 4 4 3 3 3 2 2 2 1 1 1
输出
1 2 2 3 3 3 4 4 4 1 1 2

	public static void main(String[] args) {
        int n=sc.nextInt();
        int[] a=new int[n];
        for(int i=0;i<n;i++){
            a[i]=sc.nextInt();
        }
        int b[]=new int[]{9,0,1,2,3,4,5,6,7,8};
        Arrays.sort(a);
        int[] ans=new int[n];
        int cnt=-1;
        for(int i=0;i<10;i++){
            for(int j=b[i];j<n;j+=10){
                ans[j]=a[++cnt];
            }
        }
        for(int i=0;i<n;i++)
            out.print(ans[i]+" ");
        out.flush();
    }

D 阿宁的质数(线性筛)

题目描述
阿宁有一个长度为 n 的正整数数组 a,她有很多次询问,每次询问:在数组 a 的前 x 个数中,未出现的最小质数是多少?
输入描述:
第一行输入两个正整数 n,q,表示数组的长度和询问的次数。
第二行输入 n 个正整数 ai,表示数组的每一个元素i。
接下来 q 行,每行一个正整数 x,代表一次询问。
1≤n,q≤2×10^5
1≤ai≤10^9
1≤x≤n
输出描述:
输出 q 行,表示每次询问的答案。
示例1
输入
5 5
8 2 3 6 5
1
2
3
4
5
输出
2
3
5
5
7
说明
8 不是质数,未出现的最小质数是 2。
在 8,2 中,质数有 2,未出现的最小质数是 3。
在 8,2,3 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6 中,质数有 2,3,未出现的最小质数是 5。
在 8,2,3,6,5 中,质数有 2,3,5,未出现的最小质数是 7。

法一
	static int N=(int)1e7;
    static int a[]=new int[10000001];
    static boolean b[]=new boolean[10000001];
    public static void main(String[] args) {
        int n=sc.nextInt(),q=sc.nextInt();
        for(int i=2;i<=N;i++){
            if(!b[i]){
                for(int j=i*2;j<=N;j+=i)
                    b[j]=true;
            }
        }
        int tmp=2;
        for(int i=1;i<=n;i++){
            int x=sc.nextInt();
            if(x<=N)b[x]=true;
            while(b[tmp])tmp++;
            a[i]=tmp;
        }
        while(q-->0){
            out.println(a[sc.nextInt()]);
        }
        out.flush();
    }
法二 线性筛
	static int cnt=0;
    static Set<Integer> st=new HashSet<>();
    static int res[];
    //N 的大小 3e6,大约有2e5多一点的质数
    public static void main(String[] args) {
        int n=sc.nextInt(),q=sc.nextInt();
        res=new int[n+1];

        f((int)3e6);

        cnt=1;
        for(int i=1;i<=n;i++){
            st.add(sc.nextInt());
            while(st.contains(prime[cnt]))cnt++;
            res[i]=cnt;
        }

        while(q-->0){
            out.println(prime[res[sc.nextInt()]]);
        }
        out.flush();
    }
    static int prime[]=new int[(int)3e5];
    static boolean pd[]=new boolean[(int)4e6];
    static void f(int n){//预处理2e5个质数
        Arrays.fill(pd,true);
        pd[1]=false;

        for(int i=2;i<=n;i++){
            if(pd[i])prime[++cnt]=i;

            for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
                pd[i*prime[j]]=false;
                if(i%prime[j]==0)break;
            }
        }
    }

运行时间比较

E 阿宁睡大觉(贪心)

题目描述
阿宁经常在周末睡大觉。阿宁在膜法书上了解到,她睡觉时会产生字符串 ss,计算出她的睡觉质量为
其中定义 w(z)=0,w(Z)=2 。(前者小写后者大写)
为了睡一个好大觉,阿宁使用了预测膜法知道 s 串,然后她可以最多使用 k 次del膜法。使用一次del膜法可以删除 s 串的一个字符。
阿宁想知道睡觉质量的最大值是多少?
输入描述:
第一行输入两个正整数 n、k,表示字符串的长度和del膜法的最多使用次数。
第二行输入一个字符串 s,仅包含字符 ‘z’ 和 ‘Z’。
2≤n≤2×10^5
1≤k≤2×10^5
输出描述:
一个整数,睡觉质量的最大值。
示例1
输入
3 2
ZzZ
输出
4
说明
使用一次del膜法删除中间的 ‘z’,字符串为 “ZZ”,睡眠质量为 4。
示例2
输入
3 2
zzz
输出
0

	static int n,k;
    public static void main(String[] args) {
        int n=sc.nextInt(),k=sc.nextInt();
        char c[]=(sc.next()).toCharArray();
        int l=0;
        PriorityQueue<Integer> pq=new PriorityQueue<>();
        boolean f=false;
        for(int i=0;i<n;i++){
            if(c[i]=='Z'){
                if(f){
                    pq.add(l);
                    l=0;
                }else f=true;
            }else{
                if(f)l++;
            }
        }
        int ans=0;
        while(k>0&&!pq.isEmpty()){
            int t=pq.poll();
            if(k<t)break;
            k-=t;
            ans+=4;
        }
        out.println(ans);
        out.flush();
    }

F 阿宁去游玩(图论/最短路/堆优化Dijkstra(邻接表))

题目描述
阿宁打算下次放假去游玩。一共有 n 个城市, 阿宁住在 1 号城市,去到 n 号城市游玩。
城市有两种属性,一种是炎热,另一种是酷寒,每个城市是其中一种。从一个城市前往另一个城市,如果要前往的城市和当前城市的属性相同,则需要 x 时间,否则需要 y 时间。
阿宁可以使用倒转膜法,该膜法可以使所有城市(除了阿宁当前所在的城市)的属性变化(炎热变酷寒,酷寒变炎热),花费 z 时间。倒转膜法可以使用任意次。
阿宁想尽快去到 n 号城市游玩,她想知道她最少需要多少时间到达目的地?
输入描述:
第一行输入两个正整数 n,m,表示一共有 n 个城市,m 条道路。
第二行输入三个正整数 x,y,z,表示不同动作花费的时间。
第三行输入 n 个正整数 ai,表示第 i 城市的属性,0 表示炎热,1 表示酷寒。
接下来 m 行,每行输入两个正整数 u,v,表示 u 号城市和 v 号城市有道路相连。
(道路是双向的,即 u 能走到 v,v 能走到 u)
保证 1 号城市能到达 n 号城市。
2≤n≤2×10^5
1≤m,x,y,z≤2×10^5
1≤u,v≤n
0≤ai≤1
输出描述:
一个整数,表示阿宁从 1 号城市到达 n 号城市所需要的最少时间。
示例1
输入
5 6
1 3 9
1 0 0 1 1
1 2
1 3
2 3
2 4
3 4
4 5
输出
7
说明
路径 1->3->4->5,花费时间为 3+3+1=7。
示例2
输入
3 3
1 10 2
0 1 1
1 2
1 3
2 3
输出
3
说明
在 11 号城市使用一次倒转膜法,路径 1->3,花费时间为 2+1=3。

	static int N=(int)2e5+5,M=N<<1;
    static long inf=(long)1e18;
    static int[] h=new int[N],e=new int[M],ne=new int[M];//邻接表
    static int idx=0;
    static long[] a=new long[N];
    static long[] dist=new long[N];
    static void add(int a,int b) {
        e[idx]=b;
        ne[idx]=h[a];
        h[a]=idx++;
    }

    public static void main(String[] args) throws IOException {
        int n=sc.nextInt(),m=sc.nextInt();
        long x=sc.nextInt(),y=sc.nextInt(),z=sc.nextInt();
        Arrays.fill(h,-1);
        Arrays.fill(dist,inf);
        for (int i=1;i<=n;i++) a[i]=sc.nextInt();
        for (int i=1;i<=m;i++) {
            int a=sc.nextInt(),b=sc.nextInt();
            add(a,b);
            add(b,a);
        }
        PriorityQueue<long[]> q = new PriorityQueue<>((o1, o2) -> Long.compare(o1[1], o2[1]));//lambda表达式
        q.add(new long[]{1, 0});
        while (!q.isEmpty()) {
            long[] c=q.poll();
            int u=(int)c[0];
            long d=c[1];
            for (int i=h[u];i!=-1;i=ne[i]) {//遍历所有出边
                int son=e[i];
                long w=0;
                if (a[u]!=a[son]) w=Math.min(x+z,y);
                else w=Math.min(y+z,x);
                w+=d;
                if (dist[son]>w) {
                    dist[son]=w;
                    q.add(new long[]{son,w});
                }
            }
        }
        out.println(dist[n]);
        out.flush();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值