Gemini Boy - ACM之路~
20130926 - 初级魔法练习
叉姐の魔法训练
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=32389#overview
A: Set Operatoin (POJ2443)
题意是:有n个集合(n<=1000), 每个集合有m个数ai(m<=10000, 1=<ai<=10000),同一个集合中可能有相同的数.有q个查询(q<=200000),对于每个查询a,b,问是否存在一个集合同时包含a和b。
做法就是压位加速,将每一个集合看成是一行,也成了一个1000*10000的0、1矩阵,对于每个数来书,它所在的列的0、1分布情况也就是它所在集合的情况。但问题是现在一共有1000行,2^1000肯定不行,但考虑到一个int可以存32位(2^32),1000<32*32,所以可以开32个整数,每个整数的二进制的每一位代表每一行,这样就可以在q*32的可接受的时间复杂度内查询出结果。将扫描1000变为扫描32,利用整数的位操作减少为1/32。
代码君:
package NO20130926; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.StringTokenizer; public class POJ2443 { public void run() { InputReader cin = new InputReader(System.in); PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out)); int[][] map = new int[10010][100]; int n = cin.nextInt(); for (int i = 0; i < n; i++) { int c = cin.nextInt(); for (int j = 0; j < c; j++) { int x = cin.nextInt(); map[x][i / 30] |= 1 << (i % 30); } } int q = cin.nextInt(); for (int cas = 0; cas < q; cas++) { int a = cin.nextInt(); int b = cin.nextInt(); boolean ok = false; for (int i = 0; i < 35; i++) { if ((map[a][i] & map[b][i]) > 0) { cout.println("Yes"); ok = true; break; } } if (ok == false) cout.println("No"); } cout.flush(); } public static void main(String args[]) { new POJ2443().run(); } class InputReader { public BufferedReader reader; public StringTokenizer tokenizer; public InputReader(InputStream stream) { reader = new BufferedReader(new InputStreamReader(stream)); tokenizer = null; } public InputReader() throws FileNotFoundException { reader = new BufferedReader(new FileReader("d:/input.txt")); tokenizer = null; } public String next() { while (tokenizer == null || !tokenizer.hasMoreTokens()) { try { tokenizer = new StringTokenizer(reader.readLine()); } catch (IOException e) { throw new RuntimeException(e); } } return tokenizer.nextToken(); } public int nextInt() { return Integer.parseInt(next()); } public long nextLong() { return Long.parseLong(next()); } } }
当然也可以用C++ STL的bitset或java的bitset直接来做。