STL运用


#include<bits/stdc++.h>
using namespace std;

const int maxn = 30;
vector < vector < int > > v(maxn, vector < int > ());
vector < int > pos(maxn,0);

void recover(int valx){
    int now_stx = pos[valx];
    while(v[now_stx].back() != valx){
        int idx = v[now_stx].back();
        v[idx].push_back(idx);
        v[now_stx].pop_back();
        pos[idx] = idx;
    }
}

void move(int valx,int valy){
    int now_stx = pos[valx],now_sty = pos[valy];
    int offset = v[now_stx].size() - 1;
    while(v[now_stx][offset] != valx) offset--;

    for(int i = offset;i < (int)v[now_stx].size();i++){
        v[now_sty].push_back(v[now_stx][i]);
        pos[v[now_stx][i]] = now_sty;
    }

    offset = v[now_stx].size() - offset;
    while(offset--){
        v[now_stx].pop_back();
    }

}

int main(){

    int n;cin >> n;getchar();
    string s;
    for(int i = 0;i < n;i++) pos[i] = i,v[i].push_back(i);

    while(getline(cin,s), s != "quit"){
        
        stringstream sin(s);
        string opt1,opt2;
        int idx1,idx2;
        sin >> opt1 >> idx1 >> opt2 >> idx2;
        
        if(pos[idx1] == pos[idx2]) continue;

        if(opt1 == "move"){
            if(opt2 == "onto"){
                recover(idx1),recover(idx2);
                move(idx1,idx2);
            }
            else{
                recover(idx1);
                move(idx1,idx2);
            }
        }
        else{
            if(opt2 == "onto"){
                recover(idx2);
                move(idx1,idx2);
            }
            else move(idx1,idx2);
        }

    }

    for(int i = 0;i < n;i++){
        cout << i << ":";
        for(int j = 0;j < (int)v[i].size();j++){
            cout << " " << v[i][j];
        }
        cout << "\n";
    }
    return 0;
}

这道题是典型的vector,首先我们要先建立一个vector嵌套vector,并建立一个pos来记录每一个方块现在所在的位置。一开始所有方块都在自己的初始位置上。有五种不同的操作,在有些操作之前需要将自己上方的所有方块放回他们的初始化位置,也就是放回其序号的方块上。这部操作的实现是这样的:首先我们记录要返回方块的序号,然后找到这个vector,将该方块push进去,并在原来的vector中pop掉,并将该方块的现在的位置等于其序号。然后要做的是移动,这一步操作是这样实现的:先得到两个方块现在所在的位置,找到我们要移动的方块所在vector,从最后开始往前面数,直到我们找到这个方块位置,这样做的目的是在移动后也保持方块的相对位置不变。然后从这个方块开始到最后一个方块,我们将其push到我们所要移动的目标方块上,该方块的新位置等于目标方块的序号。最后我们用移动的方块的vector的大小减去我们没有移动的方块的数目,就得到了我们移动方块的数目,将它们从该vector中pop掉。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1e3 + 50;
int t,n,k,arr[maxn];

int main(){

   scanf("%d",&t);
   while(t--){

       scanf("%d%d",&n,&k);
       for(int i = 0;i < n;i++) scanf("%d",&arr[i]);

       while(k--) next_permutation(arr,arr + n);

       for(int i = 0;i < n;i++) printf("%d ",arr[i]);
       printf("\n");

   }

   return 0;
}

next_permutation的作用是找到下一个字典序更大的序列 ,如果达到最大后就会返回false,下一次循环就会变成最小的字典序重新开始,这个题我们只需要循环k次就好了,但这个题奇怪的要死,只能用scanf来做,用cin来做就超时了,我气死了。和next的作用差不多的一个函数prev_permutation,作用是找到上一个字典序更小的序列。

#include<bits/stdc++.h>
using namespace std;

map <string,string> m;

int main(){

   string s;
   while(getline(cin,s),s != ""){
       stringstream sin(s);
       string key,value;
       sin >> value >> key;
       m[key] = value;
   }

   while(getline(cin,s)){
       map <string,string> :: iterator it = m.find(s);
       if(it != m.end()) cout << it -> second << '\n';
       else cout << "eh\n";
   }

   return 0;
}

用map来做简单的太多了,首先我们就需要用map<string,string>来做,关键字为string,值也为string类型的。我们先输入一段,用stringstream来提取以空格为分界的两个string,前面的string给值,后面的string给关键字,这样我们在后面输入关键字,通过find函数去寻找这个关键字所对应的值。

#include<iostream>
#include<cstring>
#include<sstream>
#include<map>
using namespace std;

map <int,int> m;

int main(){

   int c,k,p;
   map <int,int> :: iterator it;
   while(cin >> c,c != 0){

       if(c == 1){
           cin >> k >> p;
           m[p] = k;
       }

       else if(c == 2){
           
           if(m.empty()){
               cout << 0 << '\n';
               continue;
           } 
           else{
               it = m.end();it--;
               cout << it -> second << '\n';
               m.erase(it);
           }
       }

       else if(c == 3){

           if(m.empty()){
               cout << 0 << '\n';
               continue;
           } 
           else{
               it = m.begin();
               cout << it -> second << '\n';
               m.erase(it);
           }
       }
   }

   return 0;
}

因为map是按关键字从小到大进行排序的,所以我们要是找最大的值我们只需要找到容器末尾的前一个位置就好了,如果要找最小的我们只需要找到容器的开头就好。

#include<iostream>
#include<cstring>
#include<sstream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;

set <string> dict;

int main(){

    string s;
    while(getline(cin,s)){

        for(int i = 0;i <(int)s.size();i++){
            if(isalpha(s[i])) s[i] = tolower(s[i]);
            else s[i] = ' ';
        }

        stringstream sin(s);
        string opt;

        while(sin >> opt) dict.insert(opt);

    }

    set < string > :: iterator it = dict.begin();
    for(it;it != dict.end();it++) cout << *it << '\n';

    return 0;
}

set是一个会自动去重的容器,里面的值的大小也是按照从小到大的顺序进行排序的,所以我们可以通过将字符串输入到set中,它会自动去掉重复的字符串,并且按照字典序的大小将字符串进行一个从小到大的排序。最后通过it遍历输出每一个字符串即可。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e7 + 10;
int k,n,ele[maxn];

inline int read(){
   int x = 0,f = 1;
   char ch = getchar();
   while(!isdigit(ch)){
       if(ch == '-') f = -1;
       ch = getchar();
   }
   while(isdigit(ch)){
       x = x * 10 + (ch - '0');
       ch = getchar();
   }
   return x * f;
}

int main(){

   n = read();k = read();
   for(int i = 0;i < n;i++) ele[i] = read();
   nth_element(ele,ele + n - k,ele + n);
   printf("%d",ele[n - k]);

   return 0;
}

首先这个题时间卡的太死了,因为是1e7,所以用sort这种nlog的方式也很难过去,这个时候就需要一个复杂度为n的排序方式了。这个时候就可以用nth_element(a,a + k - 1,a + n),它会将这个区间内第k小的数放到第k - 1的位置上去,并且它左边的数都比它小,右边的数都比它大。这个时候我们只需要输出a[k - 1]就可以得到第k小的数字,一定要注意是第k - 1的位置而不是k的位置。其次这个题时间卡的太死了,就算用scanf和关同步流的cin也很难过去,这个时候我们数据的输入就得通过快读来输入了

inline int read(){
    int x = 0,f = 1;
    char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(isdigit(ch)){
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x * f;
}

这是快读的板子,一定需要熟练的快速的能够打出来

  • bitset
    这个bitset看看就好了,在某些时候会很快,一个很快的string吧。其复杂度只有N/w,N为我们所开的长度,w为32或64

  • partial_sort
    假如一个数组有100万,要找出最小的十个有顺序的数字。用普通的sort进行排序后再挑前十个太浪费时间了,我们可以用partial_sort只排(a,a + 10,a+ n)这样前10个数字是有序的。复杂度为N*logM,M为前M个数字。和nth_element不同的是,虽然都可以找到最小的几个数字,但是一个是排好序的一个是没有排好序的。前者是NlogM,后者是N,适用的场景是不同的。

  • is_sorted
    如果一个数组是按升序排列好的,就会返回一个true不然就会返回false。is_sorted_until返回第一个不按顺序的排列的元素的迭代器,如果都按顺序就会返回end()。

  • merge
    如果两个数组都是按升序或降序排列好的,那么就可以用merge函数合成到一个数组并按照统一的规则进行排序。比如1 3 5和2 4 6 可以用merge(a,a + 3,b,b + 3,c),合到一起就是1 2 3 4 5 6.

  • find
    find(first,second, x)在数组中找这个x,找到了这个元素就会返回这个元素所在的位置,不然就会返回end,我们可以通过是否在end来判断数组中有没有这个元素

  • partition
    partition(first,end,cmp)partition可以将数组中满足条件的元素放到左边,将不满足条件的元素放到右边,并返回一个分界点,就是不满足条件的第一个元素的位置。cmp函数是我们自己定义的一个bool类型的。并且这样的分组是不稳定的,如果我们需要保持分组后所有元素都保证自己的相对位置不变,就可以用stable_partition。如果我们希望将得到的分组情况给两个数组并且不希望原数组发生变化,我们可以用partition_copy来做,这样得到的结果会给两个数组并且保持相对位置不变,partition_copy(a,a + n,b,c,cmp)这样就可以得到一个满足条件的b数组和不满足条件的c数组了

  • unique
    unique(first,end)将会移除里面重复的元素,并返回第一个被移除的元素的位置,可以通过返回的值pos 用pos - a就可以得到有几个元素不重复了

  • rotate
    rotate(first,middle,last)可以将前middle个元素和后面的元素整体做一个交换,比如rotate(a,a + 3,a + n) 1 2 3 4 5,最后会得到4 5 1 2 3,并且会返回1所在的位置。

  • remove
    和unique差不多,只是多了一个参数,是我们要删除的元素,比如1 2 3 4 5
    用remove(first,end,3)就可以得到1 2 4 5并且第一个被移除元素的位置,也就是可以用pos - a得到还剩几个元素

  • fill
    fill(first,end,val)这样就可以将区间里所有元素都变成val,相当于一个int类型的memset

  • replace
    replace(first,end,被替换的值,替换的值)可以将区间的某一个值替换成另外一个值,比如1 2 2 3 4 replace(a,a + 5,2,7)就会变成1 7 7 3 4

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值