算法小技巧


众所周知,longlong不开见祖宗,每年都有很多人因此而吃亏,包括我自己,long long int 的上界建议定为1e18

//万能头
#include<bits/stdc++.h>
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

lower_bound返回数组中第一个大于等于k的迭代器,upper_bound返回数组中第一个大于k的迭代器,实现为二分,使用方法如下:

int an[]:1 1 1 2 2 3 3
lower_bound(an,an+7,2)-an  //为3
upper_bound(an,an+7,2)-an  //为4

vector<int> an:1 1 1 2 2 3 3
lower_bound(an,begin(),an.end(),2)-an.begin() //为3
upper_bound(an,begin(),an.end(),2)-an.begin() //为4

double不够时用long double,注意printf的时候double用%.nlf,long double用%.nLf.

一个vector类型的size是unsigned long long ,如果减去一个数为负数,会发生越界,注意要强制转化

输出int时带前导0,比如
printf(“%05d”,res)
若res位数大于5,则输出res,否则前面补0输出5位

自创数据:
新创一个cpp文件:

int main() {
	freopen("test.txt", "w", stdout);
	cout << 1 << "\n";
	return 0;
}

在代码文件里直接访问:

freopen("test.txt", "r", stdin);

set容器使用:不允许重复,不排序

struct cmp{
    bool operator()(pi a,pi b) const
    {
        if(a.x!=b.x)
        {
            return a.x>b.x;//按照第一个从大到小排列
        }
        else{
            return a.y<b.y;//第一个相等的时候按照第二个元素从小到大排列
        }
    }
};
set<pi,cmp> g;//也可以写成set<pi,greater<pi>> g;
    g.insert({1,2});
    g.insert({3,5});
    g.insert({3,4});
    g.insert({4,2});
    g.erase({5,2});
    for(auto it=g.begin();it!=g.end();it++)
    {
        cout<<it->x<<" "<<it->y<<"\n";
    }

erase没有删除的时候不会报错
输出:
4 2
3 4
3 5
1 2

multiset容器:允许重复的set,排序

常用二维数组转化为一维:a和b必须是从0开始

int get(int a,int b)
{
    return a*n+b;
}

在unordered_map中使用pair

struct pair_hash
{
    template<class T1, class T2>
    std::size_t operator() (const std::pair<T1, T2>& p) const
    {
        auto h1 = std::hash<T1>{}(p.first);
        auto h2 = std::hash<T2>{}(p.second);
        return h1 ^ h2;
    }
};

map使用count来查看是否存在元素

unordered_map<pair<int, bool>, int, pair_hash> Map;
pair<int, int> res = {1, 2};
Map[res] = 3;
cout << Map.count({1, 2});
输出:1

全排列:

vector<int >a;
	for (int i = 1; i <= 5; i++)
		a.push_back(i);
	while (next_permutation(a.begin(), a.end())) {
		for (int i = 0; i < 5; i++)
			cout << a[i] << " ";
		cout << "\n";
	}

string的substr函数:
string a=”abcd”
cout<<a.substr(0,2);
输出:从下标0开始的长度为2的子串,即“ab”
cout<<a.substr(1,3);
输出:从下标1开始的长度为3的子串,即“bcd”

结构体排序:return ture则a在b前面

struct Stone {
	int s, e, l;
} stone[110];
bool cmp(const Stone a, const Stone b) {
	int x = a.s * b.l;
	int y = b.s * a.l;
	if (x == y)
		return a.e > b.e;
	else
		return x < y;
}
sort(an, an + n , cmp);

pair排序(使用sort)

bool cmp(pi a, pi b) {
	return a.first < b.first;
}
sort(an, an + n , cmp);//从下标0到n排序,按照第一个元素从小到大排序

优先队列对结构体建立小根堆(队头为最小值)需要重载大于号

struct node {
	int dist, u, type;
	bool operator>(const node a) const {
		return dist > a.dist;
	}
};
priority_queue<node, vector<node>, greater<node>> heap;

优先队列对结构体建立大根堆(队头为最大值)需要重载小于号

struct node {
	int dist, u, type;
	bool operator<(const node a) const {
		return dist < a.dist;
	}
};
priority_queue<node, vector<node>, less<node>> heap;

注意auto修改值的时候要加&

unordered_map ans;
初始化为bool是false

若二维数组为局部变量,各元素的值不确定。例如:一个局部变量a[4][4]未初始化值
若二维数组为全局变量,各元素的值编译器会默认初始化为0;例如:全局变量a[4][4]未初始化

结构体初始化:需要有默认形参,不然定义结构体数组会报错。

struct ddata{
    int d,u,r;
    ddata(int dd=0,int uu=0,int rr=0):d(dd),u(uu),r(rr){}
};

位运算
求x的二进制的第k位:

x>>k&1;

比如:10010>>3&1 为0

返回x的最后一个1:


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

lowbit常用于树状数组

比如:lowbit(18):2(18为10010即返回10)

memset使用:
int:
-1 0 为本值
127为INT_MAX,0x3f为较大值,且值为0x3f3f3f3f
128为INT_MIN
double:
0x7f为最大值,0xfe为最小值
0x42为很大值,0xc2为很小值

精度问题:
使用double时候如果出现分数,可能导致相等的两个数不一样,用equal函数查看a和b是否相等:

bool equal(double a, double b) {
	if (fabs(a - b) < eps)
		return true;
	return false;
}

大顶堆:top是最大值

#define x first
#define y second
struct cmp {
	bool operator()(pi a, pi b) {
		return a.x > b.x;
	}
};
typedef pair<int,int> pi;
priority_queue<pi,vector<pi>,cmp> heap;

include的stringstream用法:

getline(cin, line);
string str = "hello world I am very happy!";
stringstream sstream(str);                                              
while (sstream) {
string substr;
sstream >> substr;

cout << substr << endl;
}
输出:
hello
world
I
am
very
happy!

文章作者: ycx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ycx !
评论
 上一篇
动态规划 动态规划
动态规划在算法中属于非常常见的类型,但想要熟练掌握仍需要下一番功夫
2024-07-27
下一篇 
图论 图论
图是计算机中常用的一种存储结构,图论是数学的一个分支,研究图上的优化算法。
2024-07-27
  目录