01背包
//朴素算法
const int N = 1010;
int dp[N][N];
int v[N],w[N];
int n,m; //物品数量 和 背包体积
int main(){
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];
for(int i = 1 ; i <= n ; i++){
for (int j = 1; j <= m; j ++ ){
if(j < v[i])
dp[i][j] = dp[i-1][j];
else{
dp[i][j] = max(dp[i-1][j-v[i]] + w[i],dp[i-1][j]);
}
}
}
cout<<dp[n][m];
return 0;
}
//优化算法(一维)
const int N = 1010;
int n,m; // m为背包容量
int f[N],v[N],w[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i++){
for (int j = m; j >= v[i]; j--){
f[j] = max(f[j],f[j-v[i]] + w[i]);
}
}
cout<<f[m];
return 0;
}
完全背包
//二维背包
const int N = 1010;
int n,m; // m为背包容量
int f[N][N],v[N],w[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];
for (int i = 1 ; i <= n ; i++){
for (int j = 0; j <= m; j ++ ){
f[i][j] = f[i-1][j];
if(j >= v[i])
f[i][j] = max(f[i][j],f[i][j-v[i]] + w[i]);
}
}
cout<<f[n][m];
return 0;
}
//优化算法(一维)
const int N = 1010;
int n,m; // m为背包容量
int f[N],v[N],w[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];
for (int i = 1; i <= n; i++){
for (int j = v[i]; j <= m; j++){
f[j] = max(f[j],f[j-v[i]] + w[i]);
}
}
cout<<f[m];
return 0;
}
并查集
int find(int x) { // 并查集
if (fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
快速幂
ll qpow(ll a, int b){ //需要取模时记得模p
ll res = 1;
while(b){
if(b & 1) res = res * a;
b >>= 1;
a = a * a;
}
return res;
}
费马小定理
(a / b) % p == (a * b^(p - 2)) % p
ll qmi(ll a,ll b,ll c) {
ll ans=1;
a %= c;
while(b){
if(b&1) ans=ans*a%c;
a=a*a%c;
b>>=1;
}
return ans%c;
}
ll divi(ll a,ll b,ll p){
b=qmi(b,p-2,p); //b的逆元
return a*b%p;
}
二分查找
int l = 0 , r = n + 1;
while(l < r){
int mid = (l + r + 1) / 2; //有加
if(check(mid)) l = mid;
else r = mid - 1; //必有减
}
前缀和
while(n--){
int l,r;
cin >> l >> r;
cout << s[r] - s[l - 1] << endl;
}
埃氏筛
/*
埃式筛
*/
int prime[maxn];
bool is_prime[maxn];
int sieve(int n){
int p = 0;
for(int i = 0; i <= n; ++i)
is_prime[i] = true;
is_prime[0] = is_prime[1] = false;
for (int i = 2; i <= n; ++i){
if(is_prime[i]){
prime[p++] = i;
for(int j = i + i; j <= n; j += i)
is_prime[j] = false;
}
}
return p; //返回素数个数
}
for (int i = 0; i < cnt; i ++){
int p = prime[i];
int s = 0, t = n;
while(t) s += t / p , t /= p; //求出质因子p的次数是多少
cout<<p<<" "<<s<<endl;
}
最大公约数、最小公倍数
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b) {
return a * b / gcd(a, b);
}
Dijkstra--迪杰斯特拉算法
/*
Dijkstra算法
*/
struct node {
int v, len;
node(int v = 0, int len = 0) :v(v), len(len) {}
bool operator < (const node &a)const { // 距离从小到大排序
return len > a.len;
}
};
vector<node>G[maxn];
bool vis[maxn];
int dis[maxn];
void init() {
for (int i = 0; i<maxn; i++) {
G[i].clear();
vis[i] = false;
dis[i] = INF;
}
}
int dijkstra(int s, int e) {
priority_queue<node>Q;
Q.push(node(s, 0)); // 加入队列并排序
dis[s] = 0;
while (!Q.empty()) {
node now = Q.top(); // 取出当前最小的
Q.pop();
int v = now.v;
if (vis[v]) continue; // 如果标记过了, 直接continue
vis[v] = true;
for (int i = 0; i<G[v].size(); i++) { // 更新
int v2 = G[v][i].v;
int len = G[v][i].len;
if (!vis[v2] && dis[v2] > dis[v] + len) {
dis[v2] = dis[v] + len;
Q.push(node(v2, dis[v2]));
}
}
}
return dis[e];
}
LIS--最长上升子序列
/*
|最长上升子序列|
*/
void solve(){
for(int i = 0; i < n; ++i){
dp[i] = 1;
for(int j = 0; j < i; ++j){
if(a[j] < a[i]){
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
}
/*
优化方法:
dp[i]表示长度为i+1的上升子序列的最末尾元素
找到第一个比dp末尾大的来代替
*/
void solve() {
for (int i = 0; i < n; ++i){
dp[i] = INF;
}
for (int i = 0; i < n; ++i) {
*lower_bound(dp, dp + n, a[i]) = a[i]; // 返回一个指针
}
printf("%d\n", *lower_bound(dp, dp + n, INF) - dp;
}
LCS--最长公共子序列
/*
求最长公共子序列
递推形式
*/
void solve() {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (s1[i] == s2[j]) {
dp[i + 1][j + 1] = dp[i][j] + 1;
}else {
dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]);
}
}
}
}
kmp--克努特-莫里斯-普拉特操作
/*
kmp算法
*/
void getnext(char str[N], int nextt[N]) {
int j = 0, k = -1;
nextt[0] = -1;
while (j < m) {
if (k == -1 || str[j] == str[k]) {
j++;
k++;
nextt[j] = k;
}
else
k = nextt[k];
}
}
void kmp(int a[N], int b[N]) {
int nextt[N];
int i = 0, j = 0;
getnext(b, nextt);
while (i < n) {
if (j == -1 || a[i] == b[j]) { // 母串不动,子串移动
j++;
i++;
}
else {
// i不需要回溯了
// i = i - j + 1;
j = nextt[j];
}
if (j == m) {
printf("%d\n", i - m + 1); // 母串的位置减去子串的长度+1
return;
}
}
printf("-1\n");
}
树状数组
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
const int N = 15010, M = 32010;
int tr[M],ans[N];
int lowbit(int x) //二进制中最后一位1
{
return x & -x;
}
void update(int x, int c) // 位置x加c
{
for (int i = x; i < M; i += lowbit(i)) tr[i] += c;
}
int query(int x) // 返回前x个数的和
{
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
int main(){
cin >> n;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);//其实这里 y 并没有什么用
x++;/*为了防止出现0的情况,给它全体横坐标加上 1 就好了。
这其实是一个很小的细节,作者但是做的时候没考虑到然后就wa了,而给每个 x 都加上 1 并不会影响结果*/
update(x,1);//更新一下树状数组,每次都给 x 后面的数据加上 1
ans[query(x)]++;/*然后查一下它的前缀和是多少,前缀和是多少就意味着是多少级
这是一个动态变化的过程,而且后面的一定比前面高
所以要实时计算*/
}
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);//输出每一个等级的数量
}
return 0;
}
线段树
// 建树,分别代表当前节点,区间左端点,区间右端点
void build(int id, int l, int r) {
if (l == r) {
pmx[id] = pre[l];
nmx[id] = nxt[l];
return;
}
int mid = (l + r) >> 1;
build(id * 2, l, mid);
build(id * 2 + 1, mid + 1, r);
pmx[id] = max(pmx[id * 2], pmx[id * 2 + 1]);
nmx[id] = max(nmx[id * 2], nmx[id * 2 + 1]);
}
//前缀和最大值
int preMax(int id, int l, int r, int s, int t) {
if (s <= l && t >= r) return pmx[id];
int mid = (l + r) >> 1;
int res = -8e18;
if (s <= mid) res = max(res, preMax(id * 2, l, mid, s, min(t, mid)));
if (t > mid) res = max(res, preMax(id * 2 + 1, mid + 1, r, max(s, mid), t));
return res;
}
//后缀和最大值
int nxtMax(int id, int l, int r, int s, int t) {
if (s <= l && t >= r) return nmx[id];
int mid = (l + r) >> 1;
int res = -8e18;
if (s <= mid) res = max(res, nxtMax(id * 2, l, mid, s, min(t, mid)));
if (t > mid) res = max(res, nxtMax(id * 2 + 1, mid + 1, r, max(s, mid), t));
return res;
}
signed main() {
IOSCC;
cin >> n >> q;
rep(i, 1, n) {
cin >> w[i];
pre[i] = pre[i - 1] + w[i];
}
per(i, 1, n) nxt[i] = nxt[i + 1] + w[i];
build(1, 1, n);
while (q--) {
}
}
(持续更新。。。)