Huge orz to damjandavkov for becoming Macedonia's first GM on codeforces. Wtf Strong!
# | User | Rating |
---|---|---|
1 | tourist | 3985 |
2 | jiangly | 3814 |
3 | jqdai0815 | 3682 |
4 | Benq | 3529 |
5 | orzdevinwang | 3526 |
6 | ksun48 | 3517 |
7 | Radewoosh | 3410 |
8 | hos.lyric | 3399 |
9 | ecnerwala | 3392 |
9 | Um_nik | 3392 |
# | User | Contrib. |
---|---|---|
1 | cry | 169 |
2 | maomao90 | 162 |
2 | Um_nik | 162 |
4 | atcoder_official | 160 |
5 | djm03178 | 158 |
5 | -is-this-fft- | 158 |
7 | adamant | 155 |
8 | Dominater069 | 154 |
9 | awoo | 152 |
10 | luogu_official | 150 |
Huge orz to damjandavkov for becoming Macedonia's first GM on codeforces. Wtf Strong!
So I want to brag a little
I got bronze medal this year, 19 points away from silver, hope I get silver next year :D
orz to EntityPlantt and mkkkkkkkk for getting bronze too, also to biserailieva for moral support
Also thanks to Bidik and MODDI for amazing team leading :D
So yesterday I sent a code of this search in a group chat as a joke but surprisingly everyone praised it and iframe_ dubbed it as "Fenwick search" and now I am farming contribution making a blog about it.
Lets say you want to search on the interval $$$[1, n)$$$ and lets say you want to find the minimal position that satisfy a certain property. Also let the minimal position that satisfies said property be $$$ans$$$
So, in regular binary search you keep a left bound and a right bound and you change them accordingly, but in Fenwick search you only keep track of the middle bound. Firstly initialize the middle bound as the highest power of 2 that is less than n.
The gist of Fenwick search is transforming the middle bound into $$$ans$$$, we do that by manipulating the bits in the middle bound. Specifically for every set bit in $$$ans$$$ we set the bit after the last set bit in the middle bound and we shift it left until it matches the desired bit in $$$ans$$$. For example, lets say we start with middle bound $$$16$$$ and we want to transform it into $$$ans = 22$$$, $$$16_{10} = 10000_2 \rightarrow 11000_2 \rightarrow 10100_2 \rightarrow 10110_2 = 22_{10} $$$
But how do we actually transform it? Well its simple, we check if the middle bound satisfies the property if so, you shift the last set bit one to the left, if it does not satisfy you need to set a new bit after the last set. You need to perform this checking and updating exactly $$$\lfloor{log2(n - 1)}\rfloor$$$. There is a single edge case, if the middle bound is $$$\ge n$$$ you always need to shift the last bit to the right.
To set a new bit after the last set you need to update the middle bound like this: $$$m = m + (m \ \text{&} \ (-m)) \gt \gt 1$$$ and to shift the last bit to the right you need to update the middle bound like this:$$$m = m - (m \ \text{&} \ (-m)) \gt \gt 1$$$
int tm = 1<<(LOG);
int ans = -1;
for(int i = 0;i < LOG;i++){
if(tm >= n)tm -= (tm & -tm) >> 1;
else if(check(tm)){
ans = tm;
tm -= (tm & -tm) >> 1;
}else tm += (tm & -tm) >> 1;
}
This is the code, $$$check(x)$$$ is function that checks the property the we are searching
That's it, sorry for my bad english I tried to make it as good as possible
Name |
---|