这是一份简易的ACM模板
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这是一份简易的ACM模板相关的知识,希望对你有一定的参考价值。
1、基础算法
__int128
typedef __int128 LL;
inline __int128 read(){
__int128 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-'0';ch=getchar();}
return x*f;
}
inline void print(__int128 x){
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar(x%10+'0');
}
快速读入 / 读入读出优化
int readint(){
int x=0, op=1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch=='-')op=-1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ x=x*10+ch-'0'; ch = getchar(); }
return x*op;
}
void write(int x){
if(x<0){x=-x;putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
STL-算法
二分查找
//lower_bound:返回第一个大于等于x的位置
int p1=lower_bound(a,a+n,x)-a;
//upper_bound:返回第一个大于x的位置
int p2=upper_bound(a,a+n,x)-a;
//lower_bound2:返回数组中第一个小于或等于x的值
int p3=lower_bound(a,a+n,x,greater<int>())-a;
//upper_bound2:返回数组中第一个小于x的值
int p4=upper_bound(a,a+n,x,greater<int>())-a;
//自定义二分规则
struct cmp_lower{ bool operator () (int a,int b){ return index[a]<b;}};
int lower_result=lower_bound(ar.begin(),ar.end(),x+1,cmp_lower())-ar.begin();
容器的二分
cout<< (myset.find(233)==myset.begin()) <<" \\n"; //查找键值的位置并返回迭代器
cout<< *myset.lower_bound(234)<<"\\n"; //返回第一个>=key的元素的迭代器
cout<< *myset.upper_bound(233)<<"\\n"; //返回第一个>key的元素的迭代器
去重、离散化:
int count = unique(a, a+n)-a;
for(int i = 0; i < count; i++)printf("%d ", a[i]);
STL-容器
优先队列:
priority_queue<int, vector<int>, greater<int> >q; //小根堆
priority_queue<int, vector<int>, less<int> >q; //大根堆
struct node{int x, y;};//比较函数
struct cmp{
bool operator()(node a, node b){ return a.x > b.x; }
};
priority_queue<node, vector<node>, cmp>q;
字符串:
string s = "123456789"; char ch[110]="233";
//构造函数
string s = string(5,'c'); //用5个字符c初始化
string s = string(ch); //用c语言字符串s初始化
//常用操作
str.substr(0, 2); //返回0开始的由2个字符组成的子串
reverse(s.begin(),s.end()); //反转字符串
int x = soti(str); //将字符串转为数字
string s = to_string(x); //将数字转换为字符串
集合、映射:
set<int>myset;
myset.insert(233);
myset.erase(233); //删除里面的某个元素(如果不存在该元素则不操作)(这里也可以用迭代器删除区间)
myset.count(233); //查询集合中是否存在某个元素
myset.clear(); //清空集合
set<int>::iterator it; //如果重名声明迭代器的时候会炸掉
set<int>::reverse_iterator rit; //反向迭代器
map<int,int>mymap; //左键右值
mymap[5] = 7; //添加元素(注意 "mymap[0];" 同样往map中添加了元素,只是没有赋值而已)
自定义集合、映射:
multiset<int>se;//可重复元素
multimap<int>ma;
unordered_set<int>se; //无序存储、基于哈希
unordered_map<int, int >ma;
struct hash_pair{
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p)const{
auto hash1 = hash<T1>{}(p.first);
auto hash2 = hash<T2>{}(p.second);
return hash1 ^ hash2;
}
};
unordered_set<pair<int,int>, hash_pair>se;
unordered_,map<pair<int,int>,int, hash_pair>se;
逆序对
#include<iostream>
using namespace std;
const int maxn = 500010;
int a[maxn]; long long ans = 0;
void MergeSort(int l, int r){
if(l >= r)return ;
int m = l+r>>1;
MergeSort(l,m);
MergeSort(m+1,r);
int i = l, j = m+1;
int t[r-l+1], k = 0;
while(i<=m && j<=r){
if(a[i]<=a[j])t[k++]=a[i++];
else{
t[k++] = a[j++];
ans += m-i+1;//加上剩余元素个数
}
}
while(i<=m)t[k++]=a[i++];
while(j<=r)t[k++]=a[j++];
for(i=l, k=0; i <= r; i++,k++)a[i]=t[k];
}
int main(){
int n;
while(cin>>n &&n){
ans = 0;
for(int i = 1; i <= n; i++)cin>>a[i];
MergeSort(1,n);
cout<<ans<<"\\n";
}
return 0;
}
高精度
#include <algorithm> // max
#include <cassert> // assert
#include <cstdio> // printf,sprintf
#include <cstring> // strlen
#include <iostream> // cin,cout
#include <string> // string类
#include <vector> // vector类
using namespace std;
struct BigInteger {
typedef unsigned long long LL;
static const int BASE = 100000000;
static const int WIDTH = 8;
vector<int> s;
BigInteger& clean(){while(!s.back()&&s.size()>1)s.pop_back(); return *this;}
BigInteger(LL num = 0) {*this = num;}
BigInteger(string s) {*this = s;}
BigInteger& operator = (long long num) {
s.clear();
do {
s.push_back(num % BASE);
num /= BASE;
} while (num > 0);
return *this;
}
BigInteger& operator = (const string& str) {
s.clear();
int x, len = (str.length() - 1) / WIDTH + 1;
for (int i = 0; i < len; i++) {
int end = str.length() - i*WIDTH;
int start = max(0, end - WIDTH);
sscanf(str.substr(start,end-start).c_str(), "%d", &x);
s.push_back(x);
}
return (*this).clean();
}
BigInteger operator + (const BigInteger& b) const {
BigInteger c; c.s.clear();
for (int i = 0, g = 0; ; i++) {
if (g == 0 && i >= s.size() && i >= b.s.size()) break;
int x = g;
if (i < s.size()) x += s[i];
if (i < b.s.size()) x += b.s[i];
c.s.push_back(x % BASE);
g = x / BASE;
}
return c;
}
BigInteger operator - (const BigInteger& b) const {
assert(b <= *this); // 减数不能大于被减数
BigInteger c; c.s.clear();
for (int i = 0, g = 0; ; i++) {
if (g == 0 && i >= s.size() && i >= b.s.size()) break;
int x = s[i] + g;
if (i < b.s.size()) x -= b.s[i];
if (x < 0) {g = -1; x += BASE;} else g = 0;
c.s.push_back(x);
}
return c.clean();
}
BigInteger operator * (const BigInteger& b) const {
int i, j; LL g;
vector<LL> v(s.size()+b.s.size(), 0);
BigInteger c; c.s.clear();
for(i=0;i<s.size();i++) for(j=0;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];
for (i = 0, g = 0; ; i++) {
if (g ==0 && i >= v.size()) break;
LL x = v[i] + g;
c.s.push_back(x % BASE);
g = x / BASE;
}
return c.clean();
}
BigInteger operator / (const BigInteger& b) const {
assert(b > 0); // 除数必须大于0
BigInteger c = *this; // 商:主要是让c.s和(*this).s的vector一样大
BigInteger m; // 余数:初始化为0
for (int i = s.size()-1; i >= 0; i--) {
m = m*BASE + s[i];
c.s[i] = bsearch(b, m);
m -= b*c.s[i];
}
return c.clean();
}
BigInteger operator % (const BigInteger& b) const { 17 行代码实现的简易 Javascript 字符串模板