AcWing 周赛41

4308. 组合字符串
比赛时没有通过,思路是对的(经过观察发现,s2字符串只会取第一个字符,而s1字符串一定取第一个字符,后面的字符取到小于s2字符串第一个字符的地方),但是遗漏了等于号。
aw比awc字典序要小,所以当找到s1中除第一个字符外,不小于s2中第一个字符的字符时退出循环。找到等于的也不继续向下找了,并且不要这个等于的。

import java.util.Scanner;

public class Main_1 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		String s1 = scanner.next();
		String s2 = scanner.next();
		int i;
		for (i = 1; i < s1.length(); i++) {
			if (s1.charAt(i) >= s2.charAt(0)) {// 漏了等于号!!!!!!
				// System.out.println(s1.charAt(i));
				break;
			}
		}
		System.out.print(s1.subSequence(0, i));
		System.out.print(s2.charAt(0));
	}
}

y总思路:枚举。
y总代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int main()
{
    string a, b;
    cin >> a >> b;
    
    string res(20, 'z');
    for (int i = 1; i <= a.size(); i ++ )
        for (int j = 1; j <= b.size(); j ++ )
            res = min(res, a.substr(0, i) + b.substr(0, j));
    
    cout << res << endl;
    return 0;
}

(枚举虽简单,但是我不敢用呀,超时咋办呀?但是大神信手拈来,因为他知道不会超时,那么借此学一下判断是否超时)
就这个题而言枚举也就是10*10的数据量,一看就不会超时。
先留在这吧,没搜到判断超时的方法。。。。。。

4309. 消灭老鼠
这个题,一上来就有思路(求每一个点与给定点形成直线的斜率,然后利用set判重),因为21年蓝桥杯我做过和这个差不多的题,但是还是还是没有AC。我就想,我去,我蓝桥杯是不是也这样。虽然已经比完了。
虽然我设成了double,但是据y总言,除法会出现精度问题,也有小伙伴说精度调到小数点后十位可以AC。
y总思路:
利用STL中的pair,存放(x-x0,y-y0).即分别存放斜率的分子和分母,不必作除法,当然结果应该约分化为最简。考虑到可能出现(-2,3)与(2,-3)的情况(这两个应该是一个,只是符号不同),我们规定如果y出现负号,那么把负号给x。
自己写的时候调了好久,一直不AC,还是许多细节问题

  1. 我考虑到在求最大公约数的时候,gcd(a,b),应该保证a>b,所以,我在y-y0大的时候交换了顺序,但是错了错了!!!交换顺序后,就不是原来的斜率了,符号可以通过同时取负来交换,但是位置顺序不能换呀!!!所以我用了两个变量来代替原来的,来求最大公约数
int a = xx;
int b = yy;
if (b > a) {
    int temp = b;
    b = a;
    a = temp;
} 
int d = gcd(a, b);
xx = xx / d;
			yy = yy / d;
  1. 还需要特判,两点形成的直线是平行或垂直于轴的,我当时想这样不需要除以最大公约是,实际还是需要的(6,0),(9,0)要变成(1,0).所以这个其实不需要拿出来特别考虑。
  2. y总用的是pair,可是Java的pair没有pair.size()函数,而且也没有插入函数。不要怀疑,我是这样写的
    Pair pair = new Pair<>(1, “One”);在java中他有时候还报错。刚刚我发现原来是这样
    Set> set2 = new HashSet>();
    这里java中的Map.Entry相当于c++中的pair。我记起来了,我蓝桥杯c++,在那题就是这样用的pair,嘿嘿,都是运气好。
    但是,虽然我一开始不会用pair,我找了别人的一份代码,他也没有用pair,而是用
    Set set = new HashSet();
    //。。。。。。
    String string = xx + “_” + yy;
    // System.out.println(string + d + xx + yy);
    set.add(string);
    代替,我去,还是人家聪明,何苦纠结pair呢!
    好了,一个小时发现了自己思路的错误,最终代码AC
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class Main_2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int x = scanner.nextInt();
        int y = scanner.nextInt();
        // node[] s = new node[n];
        Set<String> set = new HashSet<String>();
        for (int i = 0; i < n; i++) {
            int xx = scanner.nextInt();
            int yy = scanner.nextInt();
            xx -= x;
            yy -= y;
            int a = xx;
            int b = yy;
            if (b > a) {
                int temp = b;
                b = a;
                a = temp;
            } 
            int d = gcd(a, b);
            xx = xx / d;
            yy = yy / d;
            if (yy < 0) {
                xx = -xx;
                yy = -yy;
            }
            String string = xx + "_" + yy;
            set.add(string);
            
        }
        System.out.println(set.size());
    }
    
    private static int gcd(int xx, int yy) {
        // TODO Auto-generated method stub
        return yy != 0 ? gcd(yy, xx % yy) : xx;
    }
}

4310. 树的DFS
这个比赛时我直接一行代码也没敲,因为纯纯看不懂题目。
y总思路:
只能说绝!!
树的dfs遍历,要求某一棵子树的按照dfs便利的第k个节点的编号。那么我用两个数组q[i],p[i]。q[i]表示编号为i的节点在dfs便利中的序列号,p[i]表示在dfs遍历中序列号为i的节点在树中的编号,也就是这两个数组可以互相表示的。那么我要求以i为根节点的子树中在dfs中第k个被遍历到的数(包括j本身),可以通过q[p[i] + k - 1]表示。同时为了判断改节点是否存在,设置一个数组size[i]表示以i为根节点的子树的节点数(包括i本身),当k > size[i],时该节点不存在。
java的一个不好处,同样的思路,他比c++耗时,所以我在用Scanner输入时超时了,最后使用BufferedReader输入,代码才可以AC。
我的代码和思路都是仿照y总的。不得不说,dfs的代码好绝。单独欣赏一下。

private static void dfs(int i) {
		// TODO Auto-generated method stub
		size[i] = 1;
		q[i] = num;
		p[num] = i;
		num++;
		for (Integer e : v.get(i)) {
			dfs(e);
			size[i] += size[e];
		}
	}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Vector;

public class Main_3 {
	static int[] p;
	static int[] q;
	static int num;
	static int size[];
	static Vector<Vector<Integer>> v = new Vector<Vector<Integer>>();

	public static void main(String[] args) throws IOException {
//		Scanner scanner = new Scanner(System.in);//时间超限
//		int n = scanner.nextInt();
//		int k = scanner.nextInt();
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
		String[] strings = reader.readLine().split(" ");
		int n = Integer.parseInt(strings[0]);
		int k = Integer.parseInt(strings[1]);
		p = new int[n + 1];
		q = new int[n + 1];
		size = new int[n + 1];

		// Vector[] vv = new Vector()[3];
		for (int i = 0; i < n + 1; i++) {
			Vector<Integer> vv = new Vector<Integer>();
			v.add(vv);
		}
		strings = reader.readLine().split(" ");
		int index = 0;
		for (int i = 2; i < n + 1; i++) {
//			int x = scanner.nextInt();
//			Integer x = reader.read();
			v.get(Integer.parseInt(strings[index++])).add(i);
		}
		dfs(1);
		while (k > 0) {
//			int kk = scanner.nextInt();
//			int xx = scanner.nextInt();
			strings = reader.readLine().split(" ");
			int kk = Integer.parseInt(strings[0]);
			int xx = Integer.parseInt(strings[1]);
			if (size[kk] < xx) {
				// System.out.println("-1");
				writer.write("-1\n");
			} else {
				// System.out.println(p[q[kk] + xx - 1]);
				writer.write(p[q[kk] + xx - 1] + "\n");
			}
			k--;
		}
		writer.flush();
		writer.close();
		reader.close();

	}

	private static void dfs(int i) {
		// TODO Auto-generated method stub
		size[i] = 1;
		q[i] = num;
		p[num] = i;
		num++;
		for (Integer e : v.get(i)) {
			dfs(e);
			size[i] += size[e];
		}
	}
}

提一下,我之前为什么没读懂题。有一个样例是这样的
9 6 1 1 1 3 5 3 5 7 3 1 1 5 3 4 7 3 1 8 1 9
我按照他没有画出树来,我画成了右边的,明显不对,然后我就懵了,唉,实际应该是左边的,
AcWing 周赛41_第1张图片
总结一下学到了啥:
首先y总代码好简洁啊!!!!嘿嘿
熟悉树的dfs便利,并了解到qp两数组的优越性。
了解了java中的pair是Map.Entry。
学会了在java中用缓存输入,提高速度
学会了一种避免除法的方式。

你可能感兴趣的:(ACW竞赛,动态规划,算法,蓝桥杯)