STL容器

在这里插入图片描述

一:vector

vector很快,只是会占用很多内存

void solve(){
	vector<int> es;
    int n;
    cin>>n;

    rep(i,1,n){
        int x;
        cin>>x;
        es.pb(x);
    }

    sort(es.begin(),es.end());
    for(auto e:es) cout<<e<<' ';
    puts("");
    reverse(es.begin(),es.end());
    for(auto e:es) cout<<e<<' ';

    return 0;
}

input

4
0 7 2 1

output

0 1 2 7 
7 2 1 0

vector与结构体

在这里插入图片描述

一维数组

void solve() {//邻接表
    const int N = 5;
    vector<int> h[N]; // 一个包含 N 个 vector<int> 的数组

    // 添加有向边
    h[0].push_back(1);
    h[0].push_back(2);
    h[1].push_back(2);
    h[1].push_back(3);
    h[2].push_back(3);
    h[3].push_back(4);

    // 遍历每个节点的邻接列表
    for (int u = 0; u < N; u++) {
        cout << "节点 " << u << " 的邻点: ";
        // for(auto x : h[u]) cout<<x<<' ';
        for (int i = 0; i < h[u].size(); i++) {
            cout << h[u][i] << " ";
        }
        cout << endl;
    }
}

输出

节点 0 的邻点: 1 2 
节点 1 的邻点: 2 3 
节点 2 的邻点: 3 
节点 3 的邻点: 4 
节点 4 的邻点: 

h[u] 是一个 vector 对象,而 vector 支持通过下标访问其元素。通过 h[u][i] 可以访问节点 u 的第 i 个邻接节点。

区分:vector e(N)

初始化方式:

  • vector<int> e[N] 不会初始化其中的vector元素。(栈)–邻接表
  • vector<int> e(N) 创建一个具有N个元素的vector,每个元素初始化为0(默认值)。(堆)–动态数组
区分:vector path(N,N);

在这里插入图片描述

二维向量

vector<vector<int>> g(3,vector<int>(n+1));

在这里插入图片描述
在这里插入图片描述

vector<string> T(M, string(N, '*'));
等价于:char ans[i][j];(i:第i个字符串,j:字符串的长度)
M个字符串,每个字符串长度为N,初始化为*

二:stack

int main(){
	stack<int> s;
    int n;
    cin>>n;

    rep(i,1,n){
        int x;
        cin>>x;
        s.push(x);//注意不是pb
    }   
    while(s.size()){
        cout<<s.top()<<'\n';
        s.pop();
    }
    return 0;
}

input

4
2 5 6 7

output

7
6
5
2

手写栈

在这里插入图片描述

三:queue

注意不是 p b \color{RED}{注意不是pb} 注意不是pb

int n,m,a,b;
vector<int> e[N];
queue<int> q;
int vis[N];

void bfs(){
    vis[1]=1;
    q.push(1);
    while(q.size()){
        int x=q.front();
        q.pop();
        cout<<x<<'\n';
        for(auto y:e[x]){
            //去重
            if(vis[y]) continue;
            vis[y]=1;
            q.push(y);
        }
    }
}

int main(){
    cin>>n>>m;
    rep(i,1,m){
        cin>>a>>b;
        //构造a与b的无向边
        e[a].pb(b);
        e[b].pb(a);
    }

    bfs();

    return 0;
}

input

5 4
1 2
1 3
2 4 
2 5

output

1
2
3
4
5

四:unordered_set

int n,c,x;
unordered_set<int> s;

int main(){
    cin>>n;
    while(n--){
        cin>>c>>x;
        if(c==1) s.insert(x);
        else s.count(x)?puts("Y"):puts("N");
    }

    return 0;
}

input

5
1 6
1 2
1 7
2 6
2 5

output

Y
N

五:unordered_map

基于hash,只有映射关系
map相比,没有去重、排序
一旦访问过就会生成key,使用erase()清除键

int n,c;
string str;
unordered_map<string ,int> h;

int main(){
    cin>>n;
    while(n--){
        cin>>c>>str;
        if(c==1) h[str]++;
        else{
            if(h.count(str)) cout<<h[str]<<'\n';
            else puts("N");
        }
    }

    return 0;
}

input

6
1 dx
1 abc
1 dx
1 aaa
2 dx
2 ab

output

2
N

六:IOS

注意: \color{RED}{注意:} 注意:

  • 要是用到了 scanf,printf,puts,gets 这些就关掉IOS
  • getline也可以不用关IOS,因为getline也用cin

iota函数+vector

头文件

#include<numeric>

用于填充[first,last)中元素的值,起始值为value

int main(){
    int n,l,r;
    cin>>n>>l>>r;
    l--;    

    vector<int>a(n);
    iota(a.begin(),a.end(),1);
    reverse(a.begin()+l,a.begin()+r);
    rep(i,0,n-1)
        cout<<a[i]<<" \n"[i==n-1];


    return 0;
}

input

5 2 4

output

1 4 3 2 5

__builtin_popcount(x)

返回x二进制中1的 个数

bitset

bitset相当于一个bool数组,但是优点是两个bitset之间可以进行按位运算。
bitset<10>a//初始值全是0
/*
string s="1010101";
bitset<10> a1(s);
cout<<a1<<endl;//0001010101 前面补0,且编号从9逐次递减
*/
bitset<4> foo (string("1001"));
bitset<4> bar (string("0011"));
foo^=bar; //1010(foo对bar按位异或后赋值给foo)
foo&=bar; //0010(按位与后赋值给foo)
foo|=bar; //0011(按位或后赋值给foo)
foo<<=2;  //1100(左移2位,低位补0,有自身赋值)
foo>>=1;  //0110(右移1位,高位补0,有自身赋值)

a.set() //将所有位变成1
a.set(k) //将第k位变成1,超限会报错
a.set(k,1);
a.set(k,0);
a.reset() //清空bitset
a.reset(k) //把第k位变成0
a.flip() //将所有位按位取反
a.flip(k) //将第k位按位取反
a.count() //返回bitset中1的个数
a.all() //若bitset内全是1返回1,否则返回0
atcoder 358_c
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin>>n>>m;

    //char s[n][n]
    vector<string> s(n);
    rep(i,0,n-1) cin>>s[i];

    //bool b[n][10]
    vector<bitset<10>> b(n);

    rep(i,0,n-1)
        rep(j,0,m-1)
            if(s[i][j]=='o') 
                b[i][j]=1;

    int ans=n;//!!!
    for(int x=0;x<(1<<n);x++){
        bitset<10> bx(x);
        bitset<10> sum;
        rep(i,0,n-1)
            if(bx[i])
                sum |= b[i];
        if(sum.count()==m) ans=min(ans,(int)bx.count());
    }
    cout<<ans;

    return 0;
}

string

int main(){
    string s[5]={"mon","tues","wed","thur","fri"};
    rep(i,0,4){
        cout<<s[i]<<" \n"[i==4];
    }
    /*
    mon tues wed thur fri
    [回车]
    */

    return 0;
}
字词修正
s[i]=(s[i]-'a'+n)%26+'a';
转char数组
printf("%s", s);          // 编译错误
printf("%s", s.data());   // 编译通过,但是是 undefined behavior
printf("%s", s.c_str());  // 一定能够正确输出
find()功能

在这里插入图片描述
统计单词数( 1308 ) \color{blue}{统计单词数(1308)} 统计单词数(1308

string a,s;

int main(){
    cin>>a;
    getchar();//!!!
    getline(cin,s);

    // rep(i,0,SZ(s)-1){
    //     if(s[i]>='A' && s[i]<='Z') s[i]+=32;
    // }
    transform(a.begin(),a.end(),a.begin(),::tolower);//使a小写化 
    // rep(i,0,SZ(a)-1){
    //     if(a[i]>='A' && a[i]<='Z') a[i]+=32;
    // }
    transform(s.begin(),s.end(),s.begin(),::tolower);//小写化 

    s.insert(0," ");//让b前面加个空格 之后用find不怕查不到第一个 
    a=a+' ';
    a.insert(a.begin(),' ');
    //查找的话以首尾加空格,否则可能查找到其他单词里的字符相同但不是个单独的单词 
    //ec:cat != catter

    if(s.find(a)==-1){
        cout<<"-1";
    }else{
        int n=0,sum=0;
        while(s.find(a,n) != -1){
            sum++;
            n=s.find(a,n)+1;
        }
        cout<<sum<<' '<<s.find(a);
    }

    return 0;
}
字符串反转

在这里插入图片描述
在这里插入图片描述

sscanf & sprintf

1.sscanf:从字符串中解析出整数
2.sprintf:将多个整数和运算符的格式化为字符串
只能与 c h a r [ ] 兼容,无法与 s t r i n g 兼容 \color{red}{只能与char[ ]兼容,无法与string兼容} 只能与char[]兼容,无法与string兼容

int T,c,d;
char a;
char s[N],b[N];

int main(){
    
    cin>>T;
   
    while(T--){
        cin>>b;
        if(b[0]>='a' && b[0]<='z'){
            a=b[0];//如果是运算符就存入a,然后输入数字
            cin>>c>>d;
        }else{
            //如果是数字就转换b为int存储到第一个数字
            sscanf(b,"%d",&c);//不要漏了&(b->c)
            cin>>d;
        }
        memset(s,0,sizeof s);
        if(a=='a') sprintf(s,"%d+%d=%d",c,d,c+d);
        else if(a=='b') sprintf(s,"%d-%d=%d",c,d,c-d);
        else if(a=='c') sprintf(s,"%d*%d=%d",c,d,c*d);
        
        cout<<s<<endl<<strlen(s)<<endl;//输出字符串和字符串长度
    }

    return 0;
}

next_permutation

  • next_permutation只能获得下一个排列,如果要获得全排列,那么就需要先对数组进行sort排序

  • 对于排列的个数,如果出现相同的元素(9496),则使用捆绑法 A 2 2 ⋅ A 3 3 A^{2}_{2}\cdot A^{3}_{3} A22A33,否则(1234),则 A 4 4 A^{4}_{4} A44

int main(){
    string s;
    cin>>s;//输入9496

    sort(all(s));
    // cout<<s<<endl;
    int i=1;
    do{
        cout<<i<<' '<<s<<endl;
        i++;
    }while(next_permutation(all(s)));//获取下一个排列 
	/*
    1 4699
    2 4969
    3 4996
    4 6499
    5 6949
    6 6994
    7 9469
    8 9496
    9 9649
    10 9694
    11 9946
    12 9964
    */

    return 0;
}

结构体排序

#include<iostream>
#include<algorithm>//使用 next_permutation()和sort()需要导入的头文件 
using namespace std;

struct test{//结构体test 
	int val;
}; 

bool cmp(test t1,test t2){//自定义的排列 
	return t1.val<t2.val;
}

int main(){
	test t[4];//结构体数组 
	t[0].val=1;
	t[1].val=2;
	t[2].val=3;
	t[3].val=4;
	
	do{
		for(int i=0;i<4;i++){//打印排列 
			cout<<t[i].val<<' ';
		}
		cout<<endl;
	}while(next_permutation(t,t+4,cmp));//获取下一个排列 
} 

Avoid K Palindrome 2 AtCoder - abc363_c

int n,k;
string s;

int main(){
    cin>>n>>k>>s;

    sort(s.begin(),s.end());
    int ans=0;
    do{
        bool ok=true;
        rep(i,0,n-k){
            bool pal=true;
            // rep(j,1,k-1-j) 错误
                for(int j=0;j<k-1-j;j++)
                if(s[i+j]!=s[i+k-1-j]){
                    pal=false;
                    break;
                }
            if(pal){
                ok=false;
                break;
            }
        }
        if(ok) ans++;
    }while(next_permutation(s.begin(),s.end()));
    cout<<ans;
        

    return 0;
}

双指针

判断回文串

在这里插入图片描述

void solve(){
    int n;
    cin>>n;

    while(n--){
        string s;
        cin >> s;
        bool ans=1;
        int i=0,j=s.size()-1;
        while(i<j){
            if(s[i]!=s[j]){
                ans=0;
                break;
            }
            i++,j--;
        }
        if(ans) cout << "yes" << endl;
        else cout << "no" << endl;

    }
}

朴素写法

bool check(string s){
    rep(i,1,SZ(s)/2)
        if(s[i]!=s[SZ(s)-i-1]) return false;
    return true;
}

void solve(){
	int n;
	string s;
    cin >> n;

    while(n--){
        cin >> s;
        if(check(s)) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
}

调整回文串

将 s[i] 和 s[j] 变成相同字符所需的最小操作次数

在这里插入图片描述
注意: m i n 对比两个个以上要用花括号 \color{RED}{注意:min对比两个个以上要用花括号} 注意:min对比两个个以上要用花括号

    int a=5,b=9,c=6,d=0;
    cout<<min({a,b,c,d});

core code

int res;
string s;

int main(){
    cin>>s;

    for(int i=0,j=SZ(s)-1;i<j;i++,j--)
        res += min({abs(s[i] - s[j]), abs(s[i] - 26 - s[j]), abs(s[i] + 26 - s[j])});

    cout<<res;
    return 0;
}

朴素写法

void solve()
{
    string s;
    cin >> s;
    int ans = 0;
    for(int i = 0;i < s.size()/2;++i)
    {
        ans += min(abs(s[i] - s[s.size() - 1 - i]),26 -abs(s[i] - s[s.size() - 1 - i]) );
    }
    cout << ans << "\n";
}

杂题

矩阵快速打印
  • 输入图
	//数组名是首元素的地址
	//二维数组名又是一维数组的地址(行地址)
	char g[N][N];//只能为char,且输入一定没空格
	for(int i=0;i<n;i++) cin>>g[i];
  • 打印

int main(){
    a[0]=1;
    rep(i,1,6) a[i]=a[i-1]*3;//3的幂次

    cin>>n;
    int m=a[n];
    rep(i,0,m-1)
        rep(j,0,m-1)
            g[i][j]='#';
    
    dfs(n,0,0);//print .

    rep(i,0,m-1) puts(g[i]);//quick print

    return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值