Docs– changes to the documentation like README |文档
Style– style or formatting change |格式(不影响代码运行的变动)
Perf – improves code performance |优化相关,比如提升性能、体验。
Test– test a feature | 增加测试
ReFactor- A code that neither fix bug nor adds afeature. | 重构(即不是新增功能,也不是修改bug的代码变动)
Chore: Changes that do not affect the external user| 构建过程或辅助工具的变动。
Revert:回滚
Merge:代码合并。
scope
The “scope” field should be a noun that represents the part of thecodebase affected by the commit.
For example, if the commit changes the login page, the scope could be“login”. If the commit affects multiple areas of the codebase, “global”or “all” could be used as the scope.
#include<bits/stdc++.h> usingnamespace std; constint N = 1e5 + 10; int a[N], stk[N], top = -1, t = 0; structQ{int id, l, r;};
inlineintread(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; }
voidpush(int i){ while (top != -1 && a[stk[top]] <= a[i]) top --; stk[++ top] = i; }
intquery(int b, int e){ while (t < e) push(++ t); int l = 0, r = top; while (l < r) { int mid = (l + r) >> 1; if (stk[mid] >= b) r = mid; else l = mid + 1; } return a[stk[l]]; }
intmain(){ int n = read(), m = read(); for (int i = 1; i <= n; i ++) a[i] = read(); vector<Q> q; for (int i = 0; i < m; i ++) { q.push_back({i, read(), read()}); } sort(q.begin(), q.end(), [](auto &a, auto &b) { return a.r < b.r; }); vector<int> res(m); for (auto &x : q) { res[x.id] = query(x.l, x.r); } for (int &x : res) printf("%d\n", x); return0; }
#include<bits/stdc++.h> usingnamespace std; constint N = 1e5 + 10; int f[N][21];
inlineintread(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; }
intmain(){ int n = read(), m = read(); for (int i = 1; i <= n; i ++) f[i][0] = read(); for (int j = 1; j < 21; j ++) for (int i = 1; i + (1 << j) - 1 <= n; i ++) f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); while (m --) { int l = read(), r = read(); int len = log2(r - l + 1); printf("%d\n", max(f[l][len], f[r - (1 << len) + 1][len])); } return0; }
intmain(){ int n; cin >> n; vector<vector<int>> ans(2, vector<int>(4, 0)); while (n --) { int c, p; cin >> c >> p; ans[c][p] ++; } for (auto &v : ans) { for (int i = 1; i <= 3; i ++) { cout << v[i]; if (i != 3) cout << " "; } cout << endl; } auto t = ans; sort(ans.begin(), ans.end()); if (t == ans) cout << "The second win!"; else cout << "The first win!"; return0; }
RC-u2 出院
1 2 3 4 5
A:最近出了一个饮料营养等级你们知道吗?例如无糖的饮料是 A 级,可乐是 D 级…… B:那……无糖可乐是什么级别? C:AD 级吧。 A:出院! B:出什么院,你也给我进去!
// // Created by trudbot on 2023/7/15. // #include<bits/stdc++.h> usingnamespace std; #define x first #define y second
intmain(){ int n, m; cin >> n >> m; map<string, string> level; for (int i = 0; i < n; i ++) { string s, lev; cin >> s >> lev; level[s] = lev; } for (int i = 0; i < m; i ++) { string s; cin >> s; //如果已知等级 if (level.count(s)) cout << level[s] << endl; else { int cnt = 0; string res; for (auto &p : level) { if (p.x.size() < s.size() && s.substr(0, p.x.size()) == p.x //是否为前缀 && level.count(s.substr(p.x.size()))) //后缀是否已知 cnt ++, res = p.y + level[s.substr(p.x.size())]; } if (cnt != 1) res = "D"; cout << res << endl; } } return0; }
#include<bits/stdc++.h> usingnamespace std; constint N = 4010; int n, m; string name[N]; vector<int> g[N]; unordered_map<string, int> id;
vector<int> bfs(int start, int end){ queue<int> q; vector<int> last(n + 1, 0); q.push(start); while (!q.empty()) { int u = q.front(); q.pop(); if (u == end) break; for (auto &v : g[u]) if (last[v] == 0) last[v] = u, q.push(v); } vector<int> res; do { res.push_back(end), end = last[end]; } while (end != 0); return res; }
voidprint(int u, bool space){ cout << name[u] << " " << u - id[name[u]]; if (space) cout << " "; }
intmain(){ cin >> m; //编号、建图 for (int i = 1; i <= m; i ++) { string s1, s2; int st1, st2; cin >> s1 >> st1 >> s2 >> st2; if (!id.count(s1)) { n += 2, id[s1] = n - 1, name[n - 1] = name[n] = s1; } if (!id.count(s2)) { n += 2, id[s2] = n - 1, name[n - 1] = name[n] = s2; } g[id[s1] + st1].push_back(id[s2] + st2); } //取最短路径 vector<int> res(2000); for (int i = 1; i <= n; i += 2) { auto p1 = bfs(i, i + 1), p2 = bfs(i + 1, i); if (res.size() > p1.size() && p1.size() > 1) res = p1; if (res.size() > p2.size() && p2.size() > 1) res = p2; } //打印格式 for (int i = res.size() - 1; i >= 1; i --) { print(res[i], true), print(res[i - 1], true); } cout << "= ", print(res.back(), true), print(res[0], false); return0; }
另外,Bellman,Held, and Karp 的动态规划算法可以在O()时间内解决问题。在这个方法中,对每个顶点集S和其中的每一个顶点v,均做出如下的判定:是否有一条经过S中每个顶点,并且在v结束束的路径,对于每一对S和v,当且仅当存在v的邻居w满足存在一条路径经过S-v所有顶点,并在上w结束的路径时,存在路径经过中S每个顶点,并且在v结束。这个充要条件已经可以之前的动态规划计算中确认。[5][6]
For the past few days, I have been reading various explanations ofthe Binary Indexed Tree. For some reason, none of the explanations weredoing it for me. All explanations told me the same thing over and overagain. I was not able to find the motive behind this data structure,intuition behind this data structure.
Finally, I decided to sit down, check some examples, diagram themout, check stack overflow and understand it. I now understand the beautyof this data structure, and I think, I can explain it. For those whohave gone through this and also for those who don't want to go throughthis phase, I am writing this post..
Let me tell you one thing, this is going to be a longer post. I willtry to cover all the things associated with it. I have included examplesfor understanding. Give it half an hour, you will surely get new thingto learn.
Wasting no time, lets have a well defined problem.
1 2 3 4
We will be given an array. And we are asked to answer few queries. Queries will be of two types:- 1) Update X Y : Increment value at Xth index by Y. 2) Sum L R : Print sum of values at index L to R inclusive.
Lets have a look at other approaches in short, before going for BIT(Binary Indexed Tree), so that you will know the need of BIT.
We can update any value in the array in singlestep. So, update operation will need timeO(1). Also, forsum operation, we can traverse the array and find sum.That operation will take time O(n)in worst case.
One more thing we can do. At each index, we will store thecumulative frequency i.e. we will store sum of all elements before itincluding itself. We can construct this new array in . Lets say thisarray as CF[]. After that, All the sum operation willtake time since we will just subtract CF[L-1] from CF[R] to get theanswer for sum L R. But well, we will need to construct CF[] or at leastupdate CF[] every-time update operation is made. The worst case timerequired for this will be .
Since, the queries are huge in number, we can not always afford timecomplexity O(n)too. So, here comes the BIT for ourrescue.
Now, think of what we did in 2nd approach. For each index, we werestoring sum of all elements before that element to that index. Right?But because of that, we were needed to change values at all locationsfor every update.
Now think it this way, what if we store sum of some elements at eachindex? i.e. Each index will store sum of some elements the number mayvary. Similarly, for update operation also, we will need to update onlyfew values, not all. We will see how!
Formally, we will create some benchmarks. Each benchmark will storesum of all elements before that element; but other than thosebenchmarks, no other point will store sum of all elements, they willstore sum of few elements. Okay, if we can do this, what we will need todo to get sum at any point is - intelligently choosing right combinationof positions so as to get sum of all elements before that point. Andthen we will extend it to sum of elements from L to R (for this, theapproach will be same as we did in second approach). We will see thatafterwards.
Now, having done the base work, lets move ahead.
Before telling HOW will we be doing, I would like to tell you WHATare we going to do. To remind you, we are going to create BIT[] of giveninput array.
WHAT:
This is a kind of manual process I am showing.
The benchmarks I was talking about are the powers of 2. Each index,if it is a power of 2, will store the sum of all elements before that.And we will apply this repetitively so as to get what each index willstore.
Suppose, we have an array of 16 elements, [1 .. 16].
Powers of 2 are:- 1, 2, 4, 8, 16
These index will store sum of all elements before them.
Fine?
What about others?
Divide this array in two halves:- we get [1..8] and [9 .. 16].
Now think recursively what we did for array of 16, apply same forthis, okay?
Seems like little bouncer? Wait, have an example of 8 elements only.Say 8 elements are :
1
1 2 3 4 5 6 7 8
Ok, powers of 2 are: 1 2 4 8 so, in BIT[] indiced 1 2 4 8 will store1 = 1, 1 + 2 =3, 1 + 2 + .. + 4 = 10 and 1 + 2 + .. + 8 = 36respectively. Right? Remember, sum of all elements before that element?Right? Good. So, till now, BIT looks like this:-
Consider Arr1 first. Powers of 2 are:- 1 2 4 They already have theirright values, no need to update.
Now, Consider Arr2: Powers of 2 are: 1 2 4
So, at indices 1, 2 and 4 will store 5 = 5, 5 + 6 = 11, 5 + 6 + 7 + 8= 26 respectively.
These are the indices according to this new 4-element array. So,actual indices with respect to original array are 4+1, 4+2, 4+4 i.e. 5,6, 8. We will not care about index 8 as it is already filled in BIT[].Hence we will update position 5 and 6 now.
I think you guys have got what we are doing. Applying same procedureon Arr1 and Arr2, we will get 4 - two element arrays (2 from Arr1 and 2from Arr2). Follow the same procedure, don't change the value at anyindex if it is already filled, you get this BIT finally.
I think you have got what we have just done! Take each node, find sumof all nodes in its left sub-tree and add it to value of that node. Andthis is what we call is BIT.
Now, we have got the BIT. Lets move ahead and solve our realproblem.
Having this tree structure with us, it is to find sum of elementstill any index. The idea is to keep a variable ansinitialized to 0. Follow the path from root to the nodeindex. Whenever we need to follow a right link, add thevalue of current node to ans . Once we reach the node, addthat value too.
For example, If we want sum of elements upto index 3.
1> node = root, ans = 0 2> node is 4, index is 3. 3> index < node, go left 4> node = 2, index is 3. 5> index > node, add value(node) to ans and go right i.e. ans = ans + value(node 2) i.e. ans = 0 + 6 i.e. ans = 6 Now, go right 6> node = 3, index = 3 7> node == index, add value of node 3 to ans and return ans i.e. ans = ans + 6 i.e. ans = 12 return 12
In actual implementation, we will be following the reverse path i.e.from node to root.
We will go in actual implementation too. Just have look at updateoperation as well.
If we want to increment k the value atindex by say .
The idea is very similar to sum operation.
Follow the path from root to the node. Whenever we need to follow aleft link, add the value of to current node. Once we reach the node, addto that node too. This is because we will need to update the set ofnodes in the tree that include that node in its left subtree, so that itwill be consistent with our sum operation,right?index``k``k
I don't think there is any need of example for this case again.
Moving ahead to the implementation.
For this, we will play a bit with BITS -- BinaryNumbers. Here comes the fun with bits -- Binary numbers. Youwill have to do little more work here to figure out the things. I willtry my best though.
Here is the thing to be observed. If we treat 0 as LEFT and 1 asRIGHT, each node tells you the path to be followed from root to reachthat node. Really? Have example, say node 5, which has 10 there, i.e.RIGHT and LEFT. This is the path we need to follow from root to 5. Coolthing, right?
The reason why this is important to us is, our sumand update operations depends on the this path. Arethey not? You remember, Left link, right link, right? During asum, we just care about the left links we follow.During an update, we just care about the right links wefollow. This binary indexed tree does all of this super efficiently byjust using the bits in the index.
The key thing behind the efficiency of BIT is:
Given any index n, the next node on the path from root to that indexwhere we go right is directly calculated by RESETing i.e. '0' the last(right most) SET-bit from the binary representation of . Apply thisuntil we reach the root.index
Say index is 5. The path from 4 to 5 is [ 4 -> RIGHT -> 6 ->LEFT -> 5 ] i.e. we take RIGHT at 4. Binary Representation of 5 is101. RESET right-most SET-bit. 101 -> 100 4 is the one node fromwhere we will go right STOP here. We have reached the root.
Say index is 7. The path from 4 to 7 is [ 4 -> RIGHT -> 6 ->RIGHT -> 7 ] i.e. we take RIGHT at 4 and 6. Binary Representation of7 is 111. RESET right-most SET-bit. 111 -> 110 6 is the node fromwhere we will go right RESET right-most SET-bit. 110 -> 100 4 is thenode from where we will go right STOP here. We have reached theroot.
We will use this information in our implementation.
Implementation:
Now we know, how to go from any index to the root and find what allright-links come in our path.
I will repeat some part of what we have looked.
For SUM: The idea is to keep a variable initialized to 0. Follow thepath from root to the node. Whenever we need to follow a right link, addthe value of current node to . Once we reach the node, add that valuetoo.ans``index``ans
For UPDATE: Follow the path from root to the node. Whenever we needto follow a left link, add the value of to current node. Once we reachthe node, add to that node too.index``k``k
Now you have got the complete picture I guess. Everything of What wesaw, Why we saw?
For SUM, We need to follow RIGHT-links no matter from root to indexor reverse. And we also know how to do that. Right?
So algorithm is:
1 2 3 4 5 6
SUM(index): ans = 0 while(index != 0): ans += BIT[index] index = Reset_Rightmost_SET_bit(index) return ans
Now, the thing remain unanswered is: How to Reset rightmost SETbit?This is a very simple task which I have already covered in my this note.By some observations, we can arrive at a conclusion that, whenever wesubtract one from any number say n, the part before a right-most set bitremain same while part after right-most set bit gets inverted. So, justANDing these can solve our problem.
1 2
Reset_Rightmost_SET_bit(n): return n&(n-1)
Please be focused and try to understand this.
We need all left links but we can only know right links with thetechnique we studied earlier.
We know that, dropping the right-most SET bit and part after thatgives us the path from root to node.
So, zeros which come after the right-most one are not useful to us atall.
We will use both these fact and try to find a way.
You must have observed, what happens when we add a 1 to right-mostSET bit of a number? [Consider scan from right to left]
The first zero from right (which will come after i.e. left to,right-most ONE of number) turns into one
Part after (i.e. left to) that ZERO remain unchanged and Part beforethat get inverted.
Is this not the exact reverse procedure of what used to happen in SUMoperation.
This is all what we wanted!
And this is the value i.e. index from which we needed to take theleft link to reach to our node from root.
We have successfully found the left link too.
Adding one to right most one is nothing but adding place value ofright-most ONE to the number.
Hence our Update operation is as simple as:
1 2 3 4
UPDATE(index, addition): while(index < length_of_array): BIT[index] += addition index = index + (index & -index)
Try to check the similarity and difference, and you will never forgetagain.
Here I will stop. I guess you have everything what you need to knowabout Binary Indexed Tree as a data structure. Now I advice you toimplement it yourself and see if you can do it.
You can always refer to the code which I am providing you.
# About using the 2 functions:- # For update, pass index of location to be updated, input array, BIT, value to be added to original number # i.e. new value - original value # For getting sum of elements in range l to r, # Getsum returns sum of elements from beginning to index # Pass index, input array & BIT to function # getsum of l to r = getsum of r - getsum of (l-1)
def update(index, a, tree, value): # index is index to be updated, a is input array / list, tree is BIT array, value is value to be added to original # number at index location add = value n = len(a) while index<n: tree[index] += add index = index + (index & (-index))
def getsum(index, a, tree): # index is location upto which you want the sum of elements from beginning # tree is BIT[], a is input array / list n = len(a) ans = 0 while(index>0): ans += tree[index] index = index - (index & (-index)) return ans
#Get the user input n = int(raw_input("Number of Elements in array: ")) inputArray = list(map(int, raw_input("Elements in array: ").split())) inputArray.insert(0,0) # insert dummy node to have 1-based indexing
#Initialise Binary Indexed Tree to 0's considering that input array is all 0's BIT = [] for i in range(0, n): BIT.append(0)
# Now we will construct actual BIT # The 4th parameter is always an additional value which is to be added to element at index location # since we have considered input array as 0 earlier (while initialising BIT), for updating, we will pass actual # value for i in range(1, n): update(i, inputArray, BIT, inputArray[i])
If you like this, Let me know :) Like, Share, Upvote[at thetop]!!
Thank you for reading and also thanks for your patience.