您的位置:首页 > 编程语言 > Java开发

java常用acm的util总结(面向竞赛)【暂停更新】

2017-11-30 23:56 295 查看

最近想入手java敲题,奈何找了好久也没有几篇对ACMer友好的博客,没有专门总结的,有也是一些输入输出的问题,所以我想自己整理下,把acm竞赛常用的队列/优先队列,set,map,vector之类的util都整理下,再加一些java常用小技巧或者竞赛中可能坑到的地方,每一个我都争取给一个例题(老年选手也在恢复码力,题目可能比较水,希望大家见谅),希望可以为广大想入手java刷题的ACMer节省下时间~

ps:本人蒟蒻一枚,但热爱“总结”,如果本人“总结”的一些地方错误了,还请各位大佬评论更正,以防将错误知识误传给萌新~

ps:至于顺序可能比较乱,一般刷到相关的题目,查阅相关资料总结一波(其实因为老年蒟蒻选手入坑数模了,另外准备一些考试啊QAQ,再加上本蒟蒻很贪玩


java的读入输出优化

众所周知在竞赛里相比C++会慢很多,因此许多题目都单独给java开时限, 根据题目会是c++时限的2-10倍, 大家都知道c++里scanf与cin的读入输出效率不同,其实java里也有不同的读入输出方式,而且效率也大不相同,接下来我给大家总结一下我所知的几种读入输出方式~

1.最简单的系统读入输出方式

static Scanner in = new Scanner(System.in); //声明
int n = in.next(); //读入
System.out.println(ans); //输出

2.输出打印流

static Scanner in = new Scanner(new BufferedInputStream(System.in)); //亲测 这里加个buff好像并没什么用
static PrintWriter out = new PrintWriter(System.out);  //主要是这里的打印流起了很大作用
out.println(ans);  //打印结果
out.flush() //PrintWriter如果不flush或者close是看不到输出的,但是如果每输出一点东西就flush会超时,所以正确的姿势是全部完成以后一次性flush出来,这样就快了;
out.close();

3.通过读入输出buff读入输出

static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(in.readLine()); //读入的是字符串 需要转int
out.write(ans);  //输出
out.newLine(); //换行
out.flush(); //也要flush
out.close();

通过StreamTokenizer达到读入效果: 直接给一个代码

import java.io.*;

public class Main
{
public static void main(String[] args) throws IOException
// in.nextTokenizer可能抛出这个异常
{
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
// 这句是io流包装来包装去,记住就好;
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
int a, b;
while (in.nextToken() != StreamTokenizer.TT_EOF)
// 用in.nextToken()读下一个标记,StreamTokenizer.TT_EOF这个是个参数,就是EOF
{
a = (int) in.nval;
// 读进来的是double型的,所以要转成int
in.nextToken();
// 读入b值(a的值是在while循环中读入的)
b = (int) in.nval;
out.println(a + b);
}
out.flush();
// 刷新缓冲区,必须的,不然a+b会留在缓冲区
}
}


通过我的对比 以第一个标准的读入输出为标准, 第二种方式效率比第一种快半倍左右 第三种比第一种快一倍半

例题:HDU 5047  这题即是大数,也很卡读入输出,各位可以试试


优先队列(PriorityQueue)

riorityQueue是个基于优先级堆的极大优先级队列。
此队列按照在构造时所指定的顺序对元素排序,既可以根据元素的自然顺序来指定排序(参阅 Comparable),
也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。
依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)

队列检索操作 poll、remove、peek 和 element 访问处于队列头的元素。

优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组的大小。
它总是至少与队列的大小相同。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。
注意1:该队列是用数组实现,但是数组大小可以动态增加,容量无限。
注意2:此实现不是同步的。不是线程安全的。如果多个线程中的任意线程从结构上修改了列表, 则这些线程不应同时访问 PriorityQueue 实例,这时请使用线程安全的PriorityBlockingQueue 类。
注意3:不允许使用 null 元素。
注意4:此实现为插入方法(offer、poll、remove() 和 add 方法)提供 O(log(n)) 时间;
为 remove(Object) 和 contains(Object) 方法提供线性时间;
为检索方法(peek、element 和 size)提供固定时间。
注意5:方法iterator()中提供的迭代器并不保证以有序的方式遍历优先级队列中的元素。
至于原因可参考下面关于PriorityQueue的内部实现
如果需要按顺序遍历,请考虑使用 Arrays.sort(pq.toArray())。
注意6:可以在构造函数中指定如何排序。如:
PriorityQueue()
使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity)
使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。
PriorityQueue(int initialCapacity, Comparator comparator)
使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器comparator来排序其元素。
注意7:此类及其迭代器实现了 Collection 和 Iterator 接口的所有可选 方法。
PriorityQueue的内部实现
PriorityQueue对元素采用的是堆排序,头是按指定排序方式的最小元素。堆排序只能保证根是最大(最小),整个堆并不是有序的。
方法iterator()中提供的迭代器可能只是对整个数组的依次遍历。也就只能保证数组的第一个元素是最小的。
转自:传送门

一般的常用函数:

pq.poll();  //返回队首并删除队首,也可以单独删除队首
pq.element(); //返回队首
pq.add();   //添加队列
pq.size();  //队列大小
pq.clear(); //清空队列


声明一个优先队列并且重载代码:

static Queue<Integer> q = new PriorityQueue<Integer>(1,new Comparator<Integer>() //这个1是设置初始大小,并没啥用,因为多了 优先队列会扩充
{
public int compare(Integer a, Integer b)  //这里是compare函数
{
return b - a;
}
});

存结构体的优先队列:PriorityQueue<node> pq = new PriorityQueue<>(); //实现把node声明好就好了


优先队列例题:poj2010
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: