import java.util.*;
import java.lang.*;
import java.io.*;
interface SegmentedArray {
long size(); // <= 2^31 - 1
long get(long index);
SegmentedArray set(int start, int end, long value); // [start, end) <- value % 2
SegmentedArray add(int start, int end, long value); // [start, end) += value % 2
int min(int start, int end); // [start, end)
}
class BitSegmentedArray implements SegmentedArray {
long size;
long realSize;
long []storage;
public BitSegmentedArray(long size) {
this.size = size;
if (size%64!=0) this.realSize = size/64 + 1;
else this.realSize = size/64;
storage = new long [(int)realSize];
for (int i = 0; i < realSize; i++) {
storage[i] = 0;
}
}
public long size() {
return size;
}
public long get(long index) {
index--;
return storage[(int)index/64] >> (index%64) & 1;
}
public void print() {
for (int i = 0; i < this.realSize; i++) {
for (int j = 0; j < 64; j++) {
System.out.print(this.storage[i] >> j & 1);
System.out.print(" ");
}
}
System.out.println();
}
public SegmentedArray set(int start, int end, long value) {
start--;
end--;
int realStart = start/64;
int realEnd = end/64;
if (realStart != realEnd) {
for (int i = start%64; i < 64; i++) {
if (value%2 == 1) storage[realStart] |= (value&1) << i;
else if (this.get(i+1) == 1) storage[realStart] ^= ((long)1 << i);
}
for (int i = realStart + 1; i < realEnd; i++) {
if (value%2 == 0) storage[i] = 0;
else storage[i] = -1;
}
for (int i = 0; i < end%64; i++) {
if (value%2 == 1) storage[realEnd] |= (value&1) << i;
else if (this.get(i+1) == 1) storage[realEnd] ^= ((long)1 << i);
}
}
else {
for (int i = start%64; i < end%64; i++) {
if (value%2 == 1) storage[realStart] |= (value&1) << i;
else if (this.get(i+1) == 1) storage[realStart] ^= ((long)1 << i);
}
}
return this;
}
public SegmentedArray add(int start, int end, long value) {
if (value % 2 == 0) return this;
start--;
end--;
int realStart = start/64;
int realEnd = end/64;
if (realStart != realEnd) {
for (int i = start%64; i < 64; i++) {
storage[realStart] ^= (value&1) << i;
}
for (int i = realStart + 1; i < realEnd; i++) {
if (storage[i] == 0) storage[i] = -1;
else storage[i] = 0;
}
for (int i = 0; i < end%64; i++) {
storage[realEnd] ^= (value&1) << i;
}
}
else {
for (int i = start%64; i < end%64; i++) {
storage[realStart] ^= (value&1) << i;
}
}
return this;
}
public int min(int start, int end) {
start--;
end--;
int realStart = start/64;
int realEnd = end/64;
if (realStart != realEnd) {
for (int i = start%64; i < 64; i++) {
long tmp = (storage[realStart] >> i) & 1;
if (tmp != 1) return 0;
}
for (int i = realStart + 1; i < realEnd; i++) {
if (storage[i] != -1) return 0;
}
for (int i = 0; i < end%64; i++) {
long tmp = (storage[realEnd] >> i) & 1;
if (tmp != 1) return 0;
}
}
else {
for (int i = start%64; i < end%64; i++) {
long tmp = (storage[realStart] >> i) & 1;
if (tmp != 1) return 0;
}
}
return 1;
}
public static void main(String[] args) {
BitSegmentedArray b = new BitSegmentedArray (10000);
long start, end;
start = System.nanoTime();
b.set(50, 4566, 1);
end = System.nanoTime();
System.out.println("Set в BitSegmentedArray отрабатывает за " + (end - start) + " нс.");
b.set(130, 740, 0);
b.set(1000, 1084, 0);
b.set(3006, 3070, 0);
start = System.nanoTime();
long get = b.get(111);
end = System.nanoTime();
System.out.println("Get в BitSegmentedArray отрабатывает за " + (end - start) + " нс.");
System.out.println(get);
start = System.nanoTime();
b.add(76, 830, 1);
end = System.nanoTime();
System.out.println("Add в BitSegmentedArray отрабатывает за " + (end - start) + " нс.");
b.add(60, 92, 0);
start = System.nanoTime();
int minimum = b.min(130, 1400);
end = System.nanoTime();
System.out.println("Min в BitSegmentedArray отрабатывает за " + (end - start) + " нс.");
System.out.println(minimum);
}
}