大一上第十五周学习笔记

校赛拿了亚军,做出了7道题目,还行

接下来一段时间就是补题

不仅补校赛的题,还补相关知识点的题目

比如接下来搞一搞dfs序,数学

发现这两个部分之前都总结过哈哈,但时间太久遗忘了

搞起

 

12.21周一

dfs序,搞起

dfs序可以给每个节点一个id从而把树形结构转化为线性结构。

一颗子树在dfs序上就是一个区间

l[id]是节点的id,而l[id]到r[id]就是以l为根的子树的dfs序

所以可以用来判断子树,子树问题可以用树状数组线段树来搞

poj 3321

用树状数组维护就好

但我用vector超时了,要用链式前向星

这个知识点已经遗忘了……

#include<cstdio>
#include<vector>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 1e5 + 10;
vector<int> g[MAXN];
int f[MAXN], a[MAXN], n, m;
int l[MAXN], r[MAXN], id;

int lowbit(int x) { return x & (-x); }

void add(int x, int w)
{
	while(x <= n)
	{
		f[x] += w;
		x += lowbit(x);
	}
}

int sum(int x)
{
	int res = 0;
	while(x)
	{
		res += f[x];
		x -= lowbit(x);
	}
	return res;
}

void dfs(int u, int fa)
{
	l[u] = ++id;
	REP(i, 0, g[u].size())
	{
		int v = g[u][i];
		if(v == fa) continue;
		dfs(v, u);
	}
	r[u] = id;
}

int main()
{
	scanf("%d", &n);
	_for(i, 1, n - 1)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	_for(i, 1, n) add(i, 1), a[i] = 1;
	
	dfs(1, -1);
	scanf("%d", &m);
	while(m--)
	{
		char s[5]; int x;
		scanf("%s%d", s, &x);
		if(s[0] == 'Q') printf("%d\n", sum(r[x]) - sum(l[x]-1));
		else 
		{
			int id = l[x];
			if(a[id]) a[id] = 0, add(id, -1);
			else a[id] = 1, add(id, 1);
		}
	}

	return 0;
}

Problem L. 代代宗师

校赛补题

题意是每个点有权值1或0,询问以i为根节点的子树中深度为h的结点的权值和

这道题用了dfs序,我已经遗忘了这个知识点,所以当时根本没法做,不知道怎么判断i的子树内的节点

做法是每个高度都把节点的dfs序存进去,同时算出前缀和

询问时在这个高度中,一个子树的节点一定是连续的一段,因为是按照dfs序的方式进入数组的

因此就可以用二分来找出这一段序列的左右两个端点

这里有个细节卡了我一下,注意根节点的dfs序范围和子节点范围两端可能重合可能不重合

如果是本身那就都重合

如果不是本身,左端点不重合,右端点可能重合可能不重合

因此左端点用lower_bound

右端点用upper_bound - 1

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 1e5 + 10;
vector<int> g[MAXN], d[MAXN], s[MAXN];
int l[MAXN], r[MAXN], a[MAXN], n, q, id;

void dfs(int u, int fa, int dep)
{
	l[u] = ++id;
	d[dep].push_back(l[u]);
	if(!s[dep].size()) s[dep].push_back(a[u]);
	else s[dep].push_back(a[u] + s[dep][s[dep].size()-1]);
	REP(i, 0, g[u].size())
	{
		int v = g[u][i];
		if(v == fa) continue;
		dfs(v, u, dep + 1);
	}
	r[u] = id;
}

int main()
{
	scanf("%d%d", &n, &q);
	_for(i, 1, n) scanf("%d", &a[i]);
	_for(i, 1, n - 1)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	
	dfs(1, -1, 1);
	while(q--)
	{
		int v, h;
		scanf("%d%d", &v, &h);
		int L = lower_bound(d[h].begin(), d[h].end(), l[v]) - d[h].begin();
		int R = upper_bound(d[h].begin(), d[h].end(), r[v]) - d[h].begin() - 1;
		if(L == 0) printf("%d\n", s[h][R]);
		else printf("%d\n", s[h][R] - s[h][L-1]);
	}
	
	return 0;
}

 

12.22周二

继续补题

Problem M. yxq 决斗

由于 yxq 打架屡战屡胜,他已经不满足打架取胜所带来的快感,因此他转向了决斗:to be or not to be! yxq 和别人决斗,初始 yxq 血条为 a,别人血条为 b。决斗为回合制,每回合 yxq 爆头对方 的机率为 p,被对方爆头的机率为 (1 − p),被爆头者掉 1 滴血,当一方血条为 0 时,则其阵亡, 请问 yxq 活下来的概率是多少,你需要输出模 998244353 意义下的结果。

多组测试数据第一行输入一个正整数 T,表示数据组数,T ≤ 10. 每组数据输入三个正整数 a,b,p,意义见题面,p 为模 998244353 意义下的数,a, b ≤ 1000

 

这题当时是写出来了。听了题解后发现有其他做法,学习学习。

dp做法

这个数据范围是一千,所以可以用n方做法

可以用dp来解决问题。这里都是模p意义下的,就不用浮点数了,都是整数

有些细节要注意

(1)转移时越界的时候看作0,即这种状态不存在。故要每次初始化为0

(2)当一直要取MOD的时候可以两个加和乘的函数,变得很方便

(3)这题有个坑就是最后一次一定是我方打的,不能把对方打的也算进去

所以转移时要特判一下

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MOD = 998244353;
const int MAXN = 1e3 + 10;
int dp[MAXN][MAXN], p, a, b;

int add(int x, int y) { return (x + y) % MOD; }
int mul(int x, int y) { return 1ll * x * y % MOD; }

int main()
{
	int T; scanf("%d", &T);
	while(T--)
	{
		memset(dp, 0, sizeof(dp));
		int ans = 0;
		scanf("%d%d%d", &a, &b, &p);
		for(int i = a; i >= 0; i--)
			for(int j = b; j >= 0; j--)
			{
				if(i == a && j == b) 
				{
					dp[a][b] = 1;
					continue;
				}
				if(j == 0) dp[i][j] = mul(dp[i][j+1], p);
				else dp[i][j] = add(mul(dp[i+1][j], 1 - p + MOD), mul(dp[i][j+1], p));
				if(j == 0 && i > 0)	ans = add(ans, dp[i][j]);
			}
		printf("%d\n", ans);
	}
	return 0;
}

数学做法

就是高中数学推公式就行

注意一定最后一次是我方击杀

这里涉及到组合数

考试的时候是初始化阶乘来算的

现在换另一种方式,用递推初始化组合数

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MOD = 998244353;
const int MAXN = 1e3 + 10;
int dp[MAXN][MAXN], p, a, b;
int c[MAXN][MAXN << 1];

int add(int x, int y) { return (x + y) % MOD; }
int mul(int x, int y) { return 1ll * x * y % MOD; }

void init()
{
	_for(j, 0, 2000) c[0][j] = 1;
	_for(i, 1, 1000)
		_for(j, 1, 2000)
			c[i][j] = add(c[i][j-1], c[i-1][j-1]);
}

int binpow(int a, int b)
{
	int res = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = mul(res, a);
		a = mul(a, a);
	}
	return res;
}

int main()
{
	init();
	int T; scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d%d", &a, &b, &p);
		int sum = 0;
		_for(k, 0, a - 1)
			sum = add(sum, mul(c[k][b-1+k], binpow(1-p+MOD, k)));
		printf("%d\n", mul(binpow(p, b), sum));
	}
	return 0;
}

 

Problem H. 2020

求这玩意

当时一脸懵逼

首先一段的和可以转化为1到k的和,然后相减即可

这是个很常见的思路

后来了解到这可以用拉格朗日插值法

给n个点,求过这n个点的曲线

多项式函数,显然可以代入点解方程

但拉格朗日插值法可以解决这个问题,非常秀

这个自行百度吧,百度可以看懂

 

至于这道题,显然是推求和公式

如果是1次方,那么求和后是n(n + 1)/2,是个二次多项式

那么4次方,求和后就是个5次多项式

那么这里就可以用拉格朗日插值法

取x为0, 1,2, 3, 4, 5六个点,就可以列出方程,代入题目给的点就行了

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MOD = 1e9 + 7;
int F[10];

int add(int a, int b) { return (a + b) % MOD; }
int mul(int a, int b) { return 1ll * a * b % MOD; }

void init()
{
	_for(i, 1, 5)
		F[i] = add(F[i-1], pow(i, 4));
}

int binpow(int a, int b)
{
	int res = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = mul(res, a);
		a = mul(a, a);
	}
	return res;
}

int inv(int x) { return binpow(x, MOD - 2); }

int f(int n)
{
	int res = 0;
	_for(i, 0, 5)
	{
		int now = F[i];
		_for(j, 0, 5) 
			if(j != i)
				now = mul(now, n - j + MOD);
		_for(j, 0, 5)
			if(j != i)
				now = mul(now, inv(i - j + MOD));
		res = add(res, now);
	}
	return res;
}

int main()
{
	init();
	int T; scanf("%d", &T);
	while(T--)
	{
		int n; scanf("%d", &n);
		int ans = f(n + 2020) - f(2019);
		if(ans < 0) ans += MOD;  //涉及到减法可能为负,小细节注意一下 
		printf("%d\n", ans);
	}
	return 0;
}

 

12.23 周三

校赛有一道数学题没做出来,今天弄质数和约数部分,加油

 

复习线性筛

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 100 + 10;
bool is_prime[MAXN];
vector<int> prime;

void get_prime()
{
	memset(is_prime, true, sizeof(is_prime));
	is_prime[0] = is_prime[1] = false;
	REP(i, 2, MAXN)
		if(is_prime[i])
		{
			prime.push_back(i);
			for(int j = i; j < MAXN; j += i)
				is_prime[j] = false;
		}
}

int main()
{
	get_prime();
	REP(i, 0, prime.size())
		printf("%d ", prime[i]);
	
	return 0;
}

 

Problem I . 「一は全、全は一」

 

当时没啥思路

后来听了题解,感觉很秀

把因数d化成n/a

把式子列一下发现分母可以配对成n

因数个数为k

答案就是n^(k/2)

当然如果是完全平方数,那就k是奇数,要多乘一个根号n

问题是怎么快速求k

暴力会超时

这里用质因数分解,因数个数为(a1+1)(a2+1)(a3+1)……

因此要初始化质数,然后质因数分解,然后算出k

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 10;
bool is_prime[MAXN];
vector<int> prime;

int add(int a, int b) { return (a + b) % MOD; }
int mul(int a, int b) { return 1ll * a * b % MOD; }

int binpow(int a, int b)
{
	int res = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = mul(res, a);
		a = mul(a, a);
	}
	return res;
}

void get_prime()
{
	memset(is_prime, true, sizeof(is_prime));
	is_prime[0] = is_prime[1] = false;
	REP(i, 2, MAXN)
		if(is_prime[i])
		{
			prime.push_back(i);
			for(int j = i; j < MAXN; j += i)
				is_prime[j] = false;
		}
}

int num(int n)
{
	int res = 1;
	REP(i, 0, prime.size())
		if(n % prime[i] == 0)
		{
			int cnt = 0;
			while(n % prime[i] == 0)
			{
				n /= prime[i];
				cnt++;
			}
			res *= (cnt + 1);
			if(n == 1) break;
		}
	if(n > 1) res *= 2;
	return res;
}

int main()
{
	get_prime();
	int T; scanf("%d", &T);
	while(T--)
	{
		int n, t; scanf("%d", &n);
		t = num(n);
		if(t & 1) printf("%d\n", mul(binpow(n, t / 2), sqrt(n)));
		else printf("%d\n", binpow(n, t / 2));
	}
	return 0;
}

NOIP2009 Hankson 的趣味题

就是考枚举因子,可以暴力

可以手算一下,逼近极限了

10的七次方到10的八次方

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

int a0, a1, b0, b1;

int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }
int lcm(int a, int b) { return a / gcd(a, b) * b; }

int check(int x)
{
	return gcd(x, a0) == a1 && lcm(x, b0) == b1;
}

int main()
{
	int T; scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d%d%d", &a0, &a1, &b0, &b1);
		int ans = 0;
		for(int x = 1; x * x <= b1; x++)
			if(b1 % x == 0)
			{
				if(x * x == b1) ans += check(x); //完全平方数一般要特判一下,是个坑 
				else ans += check(x) + check(b1 / x);
			}		
		printf("%d\n", ans);
	}
	return 0;
}

枚举因子还可以优化

先质因数分解,然后dfs枚举出所有因子

优化效果挺明显的

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 1e5 + 10;
vector<int> prime, ve;
bool is_prime[MAXN];
int a0, a1, b0, b1;
int a[15], cnt, ans;

int gcd(int a, int b) { return !b ? a : gcd(b, a % b); }
int lcm(int a, int b) { return a / gcd(a, b) * b; }

int check(int x)
{
	return gcd(x, a0) == a1 && lcm(x, b0) == b1;
}

void get_prime()
{
	memset(is_prime, true, sizeof(is_prime));
	is_prime[0] = is_prime[1] = false;
	REP(i, 2, MAXN)
		if(is_prime[i])
		{
			prime.push_back(i);
			for(int j = i; j < MAXN; j += i)
				is_prime[j] = false;	
		} 
}

void init()
{
	int t = b1;
	ve.clear(); cnt = ans = 0;
	REP(i, 0, prime.size())
		if(t % prime[i] == 0)
		{
			ve.push_back(prime[i]);
			a[cnt] = 0;
			while(t % prime[i] == 0)
			{
				t /= prime[i];
				a[cnt]++;
			}
			cnt++;
			if(t == 1) break;
		}
	if(t > 1) a[cnt++] = 1, ve.push_back(t);
}

void dfs(int i, int now)
{
	if(i == cnt)
	{
		ans += check(now);
		return;
	}
	_for(j, 0, a[i])
	{
		int t = 1;
		_for(k, 1, j) t *= ve[i];
		dfs(i + 1, now * t);
	}
}

int main()
{
	get_prime();
	int T; scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d%d%d", &a0, &a1, &b0, &b1);
		init();
		dfs(0, 1);
		printf("%d\n", ans);
	}
	return 0;
}

对顶堆复习

可以动态维护第k大的值

复杂度logn

学算法关键是理解思想,这样就容易写出来了,而不是死背模板

对顶堆的思想很简单,就是从分界点分出两个堆,维护这两个堆就好

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

priority_queue<int> q1;
priority_queue<int, vector<int>, greater<int> > q2;

void add(int x)
{
	if(!q2.size() || x > q2.top()) q2.push(x);
	else q1.push(x);
	if(q1.size() > q2.size() + 1) q2.push(q1.top()), q1.pop();
	if(q2.size() > q1.size() + 1) q1.push(q2.top()), q2.pop();
}

int work()
{
	if(q1.size() > q2.size()) return q1.top();
	return q2.top();
}

int main()
{
	int n; scanf("%d", &n);
	_for(i, 1, n)
	{
		int x; scanf("%d", &x);
		add(x);
		if(i & 1) printf("## %d\n", work());
	}
	return 0;
}

 

复习nth_element

有些题这个函数很有用

可以把第k小的数放到第k个位置,左边的小于等于它,右边的大于等于大

要变成第k大用greater<int>

复杂度O(n)

比如计算中需要前k个最小的数,就可以用这个函数,比排序nlogn要优

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

int main()
{
	int a[] = {0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
	nth_element(a + 1, a + 3, a + 11, greater<int>()); //起始,第几个数,末尾加1 
	_for(i, 0, 10) printf("%d ", a[i]); puts("");
	return 0;
}

Problem D. YYGQ

 

这道题的难点在于怎么删去

我考试时写了链表,但一直WA,链表不好写,容易写错

正解是用栈,栈弹出元素就是删去

栈手写就好,比stl能实现更多功能

然后我因为strlen这个函数卡了很久

巨坑函数

(1)每次调用strlen都是O(n),我把这个函数写到循环里面了,就多调用了很多次导致超时

所以应该用一个变量把strlen存一下

所以注意strlen用多次的时候用变量存起来

(2)strlen的返回值为unsigned int,没有负数

所以比较的时候要注意这一点,可以强制转化成int

很多stl的size貌似也是这样

所以strlen注意一点,最好用一个int变量存一下

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 1e6 + 10;
char s[MAXN], k[MAXN];
int cnt;

bool check(char str[])
{
	int len = strlen(str);
	if(cnt < len) return false;
	for(int i = len - 1, p = cnt; i >= 0; i--, p--)
		if(str[i] != k[p]) return false;	
	cnt -= len;
	return true;
}

int main()
{
	scanf("%s", s);
	int len = strlen(s);
	REP(i, 0, len)
	{
		k[++cnt] = s[i];
		check("jl") || check("bhb") || check("jz");
	}
	
	_for(i, 1, cnt) putchar(k[i]);
	if(!cnt) puts("NULL");
	
	return 0;
}

复习矩阵快速幂

校赛考了一道

其实我早已经忘记代码怎么写了,但我记得思想

于是就写出来了

所以说学算法一定要深刻理解思想,才会流畅写得出来,而不是死记硬背代码

 

Fibonacci 第 n 项

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

int x, MOD;

struct node
{
	int c[5][5];
	node() { memset(c, 0, sizeof(c)); }
};

int add(int a, int b) { return (a + b) % MOD; }
int Mul(int a, int b) { return 1ll * a * b % MOD; }

node mul(node a, node b)
{
	node res;
	_for(i, 1, 2)
		_for(j, 1, 2)
			_for(k, 1, 2)
				res.c[i][j] = add(res.c[i][j], Mul(a.c[i][k], b.c[k][j]));
	return res;
}

node binpow(node a, int b)
{
	node res;
	res.c[1][1] = res.c[2][2] = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = mul(res, a);
		a = mul(a, a);
	}
	return res;
}

int main()
{
	scanf("%d%d", &x, &MOD);
	node a;
	a.c[1][1] = a.c[1][2] = a.c[2][1] = 1;
	
	a = binpow(a, x - 1);
	printf("%d\n", a.c[1][1]);
	
	return 0;
}

Fibonacci 前 n 项和

手算矩阵即可,多加一项和的

记得可以手算个几项检验正确性

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

int x, MOD;

struct node
{
	int c[5][5];
	node() { memset(c, 0, sizeof(c)); }
};

int add(int a, int b) { return (a + b) % MOD; }
int Mul(int a, int b) { return 1ll * a * b % MOD; }

node mul(node a, node b)
{
	node res;
	_for(i, 1, 3)
		_for(j, 1, 3)
			_for(k, 1, 3)
				res.c[i][j] = add(res.c[i][j], Mul(a.c[i][k], b.c[k][j]));
	return res;
}

node binpow(node a, int b)
{
	node res;
	res.c[1][1] = res.c[2][2] = res.c[3][3] = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = mul(res, a);
		a = mul(a, a);
	}
	return res;
}

int main()
{
	scanf("%d%d", &x, &MOD);
	node a;
	a.c[1][1] = a.c[2][1] = a.c[2][2] = 1;
	a.c[2][3] = a.c[3][2] = 1;
	
	a = binpow(a, x - 1);
	printf("%d\n", add(a.c[1][1], add(a.c[2][1], a.c[3][1])));
	
	return 0;
}

 

12.24 周四

今晚平安夜和朋友出去玩,也比较疲惫,今天就不训练了

 

12.25 周五

圣诞节去玩了

 

12.26 周六

 

前两天一来圣诞节,二来也比较疲惫,就放松休息了

今天感觉状态又恢复过来了,搞起

 

Problem K. 撒播芙兰三三的离别花瓣

这道题思维量很大,代码很简单

保持好习惯,一道不会的题尽量独立思考

问题是怎么表示这个(r1, c1), (r1, c2), (r2, c1)都有时,(r2, c2)也有

这里要把它抽象成一个图,把点看成一条边

 

 

发现成为一个联通分量后,就等价于多了一条边,也就可以符合题目说的这种条件。

所以一个点就是一个边,最后就成了很多联通分量

一条边可以减少一个联通分量

最后是全部成为一个联通分量,所以答案就是联通分量个数-1

维护联通分量用并查集

很秀,关键是想到抽象成一个图

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i < (b); i++) 
#define _for(i, a, b) for(int i = (a); i <= (b); i++) 
using namespace std;

const int MAXN = 1e5 + 10;
int f[MAXN << 1], n, m, q;

int find(int x)
{
	if(f[x] == x) return x;
	return f[x] = find(f[x]);
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	_for(i, 1, n + m) f[i] = i;
	while(q--)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		f[find(x)] = find(y + n);
	}
	
	int cnt = 0;
	_for(i, 1, n + m)
		cnt += f[i] == i;
	printf("%d\n", cnt - 1);
	
	return 0;
}

 

校赛题目补完了!!!!

 

STL

遍历容器时可以用for-range循环

for(auto v: g[u])

比如很常用的vector就可以这样遍历,省去了很多代码

auto是自动匹配类型

这只是取出这个值,要改变要加&

for(auto& v: g[u])

像其他的set,map也一样

 

还有set,multiset,map,multimap,unordered_set, unordered_map容器

可以insert,erase,count 前三个是logn,后两个是O(1)

unordered_map可以用来给string分配id
set+unordered_map用来离散化 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值