昨日cf&&Bitset
昨日cf战况
首先恭喜my friend BlackCat,他仅仅在紫名待了一把就上橙了,先是一把加了113到了紫,又一把207上到了橙色,而我还停留在可耻的绿名。他简直就是个奇迹,相信今年他一定能上到红名,并且将在不久后发明一种独属于黑猫猫的新算法。

而我为什么这把没有上大分呢,答案如下,被x了
而被x的原因呢
就是这个umap搞的鬼
因此在这里提醒各位后来的算竞人,打cf不要碰umap!打cf不要碰umap!打cf不要碰umap!重要的事情说三遍.
至于为什么不要碰umap,在这里和大家讲下
首先是umap的clear的实现机制是有很大的问题的,他在极端的情况下的复杂度是o(n^2),他的实现机制是先找到第一个值的位置然后对其进行清除,随后是第二个第三个,这就导致了速度特别的慢。
其次是umap和map的底层实现是不一样的,umap的底层实现是哈希,而map是红黑树,这就造成了cf别人会通过x人来卡哈希冲突,也就导致时间复杂度再次到达了o(n^2),这也是我被卡的问题,随后我把umap改成了map果然马上过了。。。
白瞎了我的90分啊!!!结果被x后变成了-7。。。
Bitset
之前我是只听说过这个的,但由于碰到了一道题让我专门去学了一下,然后我发现,这个东西好tm得涩情啊,实在太涩都忍不住出来了!
首先来看看我碰到的一道题


这是杭电春季训练营的题目,赛后应该会放出来。
赛时的时候我想不太出这题有什么方法能做出来,因为我的方法成功tle了

这是我原先的做法,反正也是一种暴力的做饭,毕竟当时黑猫猫在赛时和我说这题的做法很暴力,但我是真想不出来该怎么在有限的资源下维护这个。
这就是bitset的涩情之处了,bitset能十分高效得维护这种状态
bitset本质上是一串二进制,但是你可以十分方便得对其进行微操,而且时间复杂度和空间复杂度还很低
#include<bits/stdc++.h>
using namespace std;
const char nl = '\n';
typedef long long ll;
typedef long double ld;
using i64 = unsigned long long;
using i32 = unsigned;
using i128 = unsigned __int128;
#define all(x) (x).begin(), (x).end()
void solve(){
int n,m,k;
cin >> n >> m >> k;
vector a(n,vector<int>(m));
for(int i = 0;i < n;i++){
for(int j = 0; j < m;j++){
cin >> a[i][j];
a[i][j]--;
}
}
vector b(n,vector<bitset<2000>>(m));
b[0][0].set(a[0][0]);
int ans = 0;
if(b[0][0].count() == k){
ans++;
}
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
if(i != 0){
b[i][j] |= b[i - 1][j];
}
if(j != 0){
b[i][j] |= b[i][j - 1];
}
b[i][j].set(a[i][j]);
if(b[i][j].count() == k){
ans++;
}
}
}
cout << ans << nl;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t = 1;
cin >> t;
while(t--){
solve();
}
return 0;
}
这是抄自黑猫猫的正确代码,在这个代码中可以学到几点:
- bitset
p 这是初始化bitset的方式,其中N表示的是有多少位二进制 - set(k)方法是对括号内的数进行转化,默认是将k设置为1,当然如果你写set(k,0),那也可以设置为0
- bitset可以进行正常的位运算
那么知道了这些后题目只剩下暴力解决了
如果想了解更多bitset的推荐阅读扶苏姐姐写的博客
最后预祝黑猫猫和loser群的群u在接下来的五月份中取得不错的acm成绩

浙公网安备 33010602011771号