PloadyFree

Bitset with get segment FULL

Nov 26th, 2018
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.00 KB | None | 0 0
  1. https://official.contest.yandex.ru/opencupXIX/contest/10686 Problem C.Array
  2.  
  3.  
  4. package net.egork;
  5.  
  6. import net.egork.io.InputReader;
  7. import net.egork.io.OutputWriter;
  8.  
  9. import java.util.Arrays;
  10. import java.util.Random;
  11.  
  12. import static java.lang.Math.min;
  13. import static java.util.Arrays.copyOfRange;
  14. import static java.util.Arrays.sort;
  15.  
  16. public class TaskAFuckingArray {
  17.     public void solve(int testNumber, InputReader in, OutputWriter out) {
  18.         if (false) new Tester().test();
  19.         int n = in.readInt();
  20.         int[] a = in.readIntArray(n);
  21.         int answer = new Solver().solve(a);
  22.         out.print(answer);
  23.     }
  24.  
  25.     class Tester {
  26.         Random rnd = new Random(239);
  27.  
  28.         void test() {
  29.             for (int t = 0; ; t++) {
  30.                 int n = 6;
  31.                 int[] a = new int[n];
  32.                 for (int i = 0; i < n; i++) a[i] = 2 + rnd.nextInt(200);
  33.                 int nai = new Naive().solve(a.clone());
  34.                 int sol = new Solver().solve(a.clone());
  35.                 if (nai != sol) {
  36.                     System.err.println(Arrays.toString(a));
  37.                     System.err.println(nai);
  38.                     System.err.println(sol);
  39.                     System.err.println(t);
  40.                 }
  41.             }
  42.         }
  43.     }
  44.  
  45.     class Naive {
  46.         int solve(int[] a) {
  47.             n = a.length;
  48.             this.a = a;
  49.             used = new boolean[n];
  50.             maxAnswer = 0;
  51.             for (int i = 0; i < n; i++) {
  52.                 used[i] = true;
  53.                 dfs(1, a[i]);
  54.                 used[i] = false;
  55.             }
  56.             return maxAnswer;
  57.         }
  58.  
  59.         int n;
  60.         int[] a;
  61.         boolean[] used;
  62.         int maxAnswer;
  63.         void dfs(int at, int answer) {
  64.             if (at == n) {
  65.                 if (maxAnswer < answer) {
  66.                     maxAnswer = answer;
  67.                 }
  68.                 return;
  69.             }
  70.             for (int i = 0; i < n; i++) {
  71.                 if (!used[i]) {
  72.                     used[i] = true;
  73.                     dfs(at + 1, answer % a[i]);
  74.                     used[i] = false;
  75.                 }
  76.             }
  77.         }
  78.     }
  79.  
  80.     class Solver {
  81.         int solve(int[] a) {
  82.             int n = a.length;
  83.             sort(a);
  84.  
  85.             if (a[0] < a[1]) {
  86.                 return a[0];
  87.             }
  88.  
  89.             int n1 = 1;
  90.             for (int i = 1; i < n; i++) {
  91.                 if (a[i] != a[i - 1]) {
  92.                     a[n1++] = a[i];
  93.                 }
  94.             }
  95.             n = n1;
  96.             a = copyOfRange(a, 0, n1);
  97.  
  98.             MyBitset answer = new MyBitset(a[n - 1] + 1);
  99.             answer.set(a[n - 1]);
  100.             answer.set(0);
  101.             for (int i = n - 2; i >= 0; i--) {
  102.                 for (int j = a[i]; j <= a[n - 1]; j += a[i]) {
  103.                     int k = min(j + a[i] - 1, a[n - 1]);
  104.                     MyBitset sub = answer.get(j, k);
  105.                     answer.makeOr(sub);
  106.                 }
  107.                 answer.set(a[i]);
  108.             }
  109.  
  110.             for (int i = a[0] - 1; ; i--) {
  111.                 if (answer.get(i)) {
  112.                     return i;
  113.                 }
  114.             }
  115.         }
  116.     }
  117.  
  118.     int type_size_bits = 6;
  119.     int type_size = 1 << type_size_bits;
  120.     int last_bits = (1 << type_size_bits) - 1;
  121.  
  122.     class MyBitset {
  123.         long[] a;
  124.         int bucketCount;
  125.  
  126.         MyBitset(int size) {
  127.             if ((size & last_bits) != 0) size += last_bits;
  128.             bucketCount = size >> type_size_bits;
  129.             a = new long[bucketCount];
  130.         }
  131.  
  132.         void set(int at) {
  133.             a[at >> type_size_bits] |= 1L << (at & last_bits);
  134.         }
  135.  
  136.         boolean get(int at) {
  137.             long res = a[at >> type_size_bits] & (1L << (at & last_bits));
  138.             return res != 0;
  139.         }
  140.  
  141.         MyBitset get(int l, int r) {
  142.             int size = r - l + 1;
  143.             MyBitset res = new MyBitset(size);
  144.  
  145.             int startBucket = l >> type_size_bits;
  146.             int endBucket = r >> type_size_bits;
  147.             if (startBucket == endBucket) {
  148.                 for (int i = l; i <= r; i++) {
  149.                     if (get(i)) {
  150.                         res.set(i - l);
  151.                     }
  152.                 }
  153.                 return res;
  154.             }
  155.  
  156.             int cut_bits = 0;
  157.             if ((l & last_bits) != 0) {
  158.                 for (int i = l; (i & last_bits) != 0; i++) {
  159.                     if (get(i)) {
  160.                         res.set(i - l);
  161.                     }
  162.                     cut_bits++;
  163.                 }
  164.                 startBucket++;
  165.             }
  166.             if ((r & last_bits) != last_bits) {
  167.                 for (int i = r; (i & last_bits) != last_bits; i--) {
  168.                     if (get(i)) {
  169.                         res.set(i - l);
  170.                     }
  171.                 }
  172.                 endBucket--;
  173.             }
  174.             for (int i = startBucket; i <= endBucket; i++) {
  175.                 int bucket0 = i - startBucket;
  176.                 long cur = a[i];
  177.                 if (cut_bits == 0) {
  178.                     res.a[bucket0] = cur;
  179.                     continue;
  180.                 }
  181.                 long head = cur & ((1L << (type_size - cut_bits)) - 1);
  182.                 long tail = cur ^ head;
  183.                 res.a[bucket0] |= head << cut_bits;
  184.                 res.a[bucket0 + 1] |= tail >>> (type_size - cut_bits);
  185.             }
  186.  
  187.             return res;
  188.         }
  189.  
  190.         void makeOr(MyBitset other) {
  191.             for (int i = 0; i < other.bucketCount; i++) {
  192.                 a[i] |= other.a[i];
  193.             }
  194.         }
  195.  
  196.         @Override
  197.         public String toString() {
  198.             String s = "";
  199.             for (int i = 0; i < bucketCount; i++) {
  200.                 for (int j = 0; j < type_size; j++) {
  201.                     if (((a[i] >> j) & 1) == 1) {
  202.                         s += (i * type_size + j) + " ";
  203.                     }
  204.                 }
  205.             }
  206.             return s;
  207.         }
  208.     }
  209. }
Advertisement
Add Comment
Please, Sign In to add comment