Skip to content

Commit e802f56

Browse files
authored
Merge pull request #247 from cpinitiative/ordered-sets-module-java
Ordered sets module java
2 parents 9de234a + 4c95767 commit e802f56

File tree

1 file changed

+164
-7
lines changed

1 file changed

+164
-7
lines changed

content/3_Silver/Intro_Ordered.mdx

+164-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
id: intro-ordered
33
title: 'More Operations on Ordered Sets'
4-
author: Darren Yao, Benjamin Qi
4+
author: Darren Yao, Benjamin Qi, Andrew Wang
55
prerequisites:
66
- intro-sets
77
- binary-search-sorted
@@ -146,7 +146,14 @@ Suppose that we replace `s.upper_bound(7)` with `upper_bound(begin(s),end(s),7)`
146146

147147
<JavaSection>
148148

149-
The ordered set also allows four additional operations: `first`, which returns the lowest element in the set, `last`, which returns the highest element in the set, `lower`, which returns the greatest element strictly less than some element, and `higher`, which returns the least element strictly greater than it.
149+
The ordered set (TreeSet) allows for a multitude of additional operations:
150+
151+
- `first()`: returns the lowest element in the set
152+
- `last()`: returns the greatest element in the set
153+
- `lower(E v)`: returns the greatest element strictly less than `v`
154+
- `floor(E v)`: returns the greatest element less than or equal to `v`
155+
- `higher(E v)`: returns the least element strictly greater than `v`
156+
- `ceiling(E v)`: returns the least element greater than or equal to `v`
150157

151158
```java
152159
TreeSet<Integer> set = new TreeSet<Integer>();
@@ -351,10 +358,6 @@ We'll use iterators extensively.
351358
352359
<Spoiler title="Solution">
353360
354-
<LanguageSection>
355-
356-
<CPPSection>
357-
358361
Let the bit string be $s=s_0s_1s_2\ldots,s_{n-1}$. In the set `dif`, we store all indices $i$ such that $s_i\neq s_{i-1}$ (including $i=0$ and $i=n$). If the elements of `dif` are $0=dif_1<dif_2<\cdots<dif_k=n$, then the longest length is equal to
359362
360363
$$
@@ -365,6 +368,11 @@ We can store each of these differences in a multiset `ret`; after each inversion
365368

366369
Inverting a bit at a 0-indexed position `x` corresponds to inserting `x` into `dif` if it not currently present or removing `x` if it is, and then doing the same with `x+1`. Whenever we insert or remove an element of `dif`, we should update `ret` accordingly.
367370

371+
372+
<LanguageSection>
373+
374+
<CPPSection>
375+
368376
```cpp
369377
#include <bits/stdc++.h>
370378
using namespace std;
@@ -385,7 +393,7 @@ void modify(int x) {
385393
ret.insert(b-a);
386394
dif.erase(it); // remove x from dif
387395
} else { // x is not currently in dif, insert it
388-
it = dif.insert(x).first; // inser x into dif
396+
it = dif.insert(x).first; // insert x into dif
389397
// it = iterator corresponding to x
390398
int a = *prev(it), b = *next(it);
391399
ret.erase(ret.find(b-a)); // update ret
@@ -409,10 +417,94 @@ int main() {
409417
}
410418
```
411419

420+
</CPPSection>
421+
422+
<JavaSection>
423+
424+
<Warning>
425+
426+
Java solutions are too slow for the CSES. Use C++ instead to get AC.
427+
428+
</Warning>
429+
430+
```java
431+
432+
import java.io.*;
433+
import java.util.*;
434+
435+
class BitInversion{
436+
public static TreeMap<Integer, Integer> ret = new TreeMap<Integer, Integer>();
437+
public static String s;
438+
public static int m;
439+
public static TreeSet<Integer> dif = new TreeSet<Integer>();
440+
441+
public static void modify(int x){
442+
if(x == 0 || x == s.length()) return;
443+
if(dif.contains(x)){ // x is currently present in dif, remove it
444+
int a = dif.lower(x), b = dif.higher(x);
445+
remove(x-a); remove(b-x); // update ret
446+
add(b-a);
447+
dif.remove(x); // remove x from dif
448+
}
449+
else{
450+
dif.add(x); // insert x into dif
451+
int a = dif.lower(x), b = dif.higher(x);
452+
remove(b-a); // update ret
453+
add(x-a); add(b-x);
454+
}
455+
}
456+
public static void main(String[] args) throws IOException
457+
{
458+
BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
459+
PrintWriter out = new PrintWriter(System.out);
460+
s = sc.readLine();
461+
m = Integer.parseInt(sc.readLine());
462+
dif.add(0); dif.add(s.length());
463+
for (int i = 0; i < s.length() -1; i++){
464+
if(s.charAt(i) != s.charAt(i+1)) dif.add(i+1); // initialize dif
465+
}
466+
for (int it : dif){
467+
if(dif.higher(it) != null) add(dif.higher(it) - it); // initialize ret
468+
}
469+
StringTokenizer st = new StringTokenizer(sc.readLine());
470+
for (int i = 0; i < m; i++){
471+
int x = Integer.parseInt(st.nextToken()); // 1-indexed position
472+
modify(x-1); modify(x);
473+
out.println(ret.lastKey());
474+
}
475+
out.close();
476+
}
477+
478+
static void add(int x){
479+
if(ret.containsKey(x)){
480+
ret.put(x, ret.get(x) + 1);
481+
} else {
482+
ret.put(x, 1);
483+
}
484+
}
485+
486+
static void remove(int x){
487+
ret.put(x, ret.get(x) - 1);
488+
if(ret.get(x) == 0){
489+
ret.remove(x);
490+
}
491+
}
492+
}
493+
494+
```
495+
496+
</JavaSection>
497+
498+
</LanguageSection>
499+
412500
<br />
413501

414502
Note that multiset has a high constant factor, so replacing `ret` with a priority queue and an array that stores the number of times each integer occurs in the priority queue reduces the runtime by a factor of 2.
415503

504+
<LanguageSection>
505+
506+
<CPPSection>
507+
416508
```cpp
417509
#include <bits/stdc++.h>
418510
using namespace std;
@@ -459,6 +551,71 @@ int main() {
459551

460552
</CPPSection>
461553

554+
<JavaSection>
555+
556+
```java
557+
558+
import java.io.*;
559+
import java.util.*;
560+
561+
class BitInversion{
562+
public static PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
563+
public static String s;
564+
public static int m;
565+
public static TreeSet<Integer> dif = new TreeSet<Integer>();
566+
public static int cnt[];
567+
public static void add(int x){
568+
cnt[x]++;
569+
pq.add(x);
570+
}
571+
public static void modify(int x){
572+
if(x == 0 || x == s.length()) return;
573+
if(dif.contains(x)){ // x is currently present in dif, remove it
574+
int a = dif.lower(x), b = dif.higher(x);
575+
cnt[x-a]--; cnt[b-x]--; // update ret
576+
add(b-a);
577+
dif.remove(x); // remove x from dif
578+
}
579+
else{
580+
dif.add(x); // insert x into dif
581+
int a = dif.lower(x), b = dif.higher(x);
582+
cnt[b-a]--; // update ret
583+
add(x-a); add(b-x);
584+
}
585+
}
586+
public static void main(String[] args) throws IOException
587+
{
588+
BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
589+
PrintWriter out = new PrintWriter(System.out);
590+
s = sc.readLine();
591+
m = Integer.parseInt(sc.readLine());
592+
cnt = new int[s.length()+1];
593+
dif.add(0); dif.add(s.length());
594+
for (int i = 0; i < s.length() -1; i++){
595+
if(s.charAt(i) != s.charAt(i+1)) dif.add(i+1); // initialize dif
596+
}
597+
for (int it : dif){
598+
if(dif.higher(it) != null){
599+
add(dif.higher(it) - it);
600+
}
601+
}
602+
StringTokenizer st = new StringTokenizer(sc.readLine());
603+
for (int i = 0; i < m; i++){
604+
int x = Integer.parseInt(st.nextToken()); // 1-indexed position
605+
modify(x-1); modify(x);
606+
while(cnt[pq.peek()] == 0) pq.poll();
607+
// pop elements that should no longer be present in priority queue
608+
out.println(pq.peek());
609+
}
610+
out.close();
611+
}
612+
613+
}
614+
615+
```
616+
617+
</JavaSection>
618+
462619
</LanguageSection>
463620

464621
</Spoiler>

0 commit comments

Comments
 (0)