专题3:STL

1、map

和python中的字典类似,键值对

map 与  unordered_map 的异同点:

map:中是排好序了的,红黑树,有序是它最大的优点,占空间,lgn时间复杂度

unordered_map :内部使用了希哈表,查找速度很快,但是希哈表建立耗时,所以查找问题就用 unordered_map 比较好

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e5+5;
map<ll,int>sum;
int main()
{
    int n,a,b,c,d,e,f;
    scanf("%d%d%d%d%d%d%d",&n,&a,&b,&c,&d,&e,&f);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                 sum[i*a+j*c+k*e]++;
    ll ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                 ans+=sum[i*b+j*d+k*f];
    printf("%lld",ans);
 
    return 0;
}
 
/**************************************************************
    Problem: 4018
    User: 2019UPC110
    Language: C++
    Result: 正确
    Time:930 ms
    Memory:3620 kb
****************************************************************/

2、一维前缀和 加 队列

问题 B: 最大子序和

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
    例如 1,-3,5,1,-2,3
    当m=4时,S=5+1-2+3=7
    当m=2或m=3时,S=5+1=6 

 

输入

第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和 

输出

一个数,数出他们的最大子序和 
 

样例输入 Copy

6 4
1 -3 5 1 -2 3

样例输出 Copy

7

提示

30%满足 n,m<=100
50%满足 n,m<=3000
100%满足n,m<=300000

 

 


#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int> pp;
const int N=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double pi=acos(-1);
int A[300005],q[300005];
int main()
{
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A[i]);
         A[i]+=A[i-1];
    }
    int l=1,r=1;
    for(int i=1;i<=n;i++)
    {
        while(l<=r&&q[l]<i-m) l++; //判断是否出队,不能超过m
        ans=max(ans,A[i]-A[q[l]]);
        while(l<=r&&A[q[r]]>=A[i]) r--;
        q[++r]=i;//保存左边的位置
 
    }
   printf("%d",ans);
    return 0;
}
 
/**************************************************************
    Problem: 14832
    User: 2019UPC110
    Language: C++
    Result: 正确
    Time:39 ms
    Memory:4368 kb
****************************************************************/

学长的 单调栈 加 一维前缀和 

//#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 500;
const int mod = 998244353;
const double pi = acos(-1);
const int inf = 1e9;
int n,m,maxx,ans,l;
int a[N];
deque <int> q;
int main()
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//    ios::sync_with_stdio(false);
//    cin.tie(NULL);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", a + i),a[i] += a[i - 1];
    q.emplace_back(0);
    ans = a[1];
    for (int i = 1; i <= n; ++i)
    {
        if (!q.empty() && q.front() < i - m)
            q.pop_front();
        ans = max(ans, a[i] - a[q.front()]);
        while (!q.empty() && a[q.back()] >= a[i])
            q.pop_back();
        q.push_back(i);
    }
    printf("%d\n", ans);
    return 0;
}

去重、map、set、排列组合 

问题 K: Candy Distribution II

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

There are N boxes arranged in a row from left to right. The i-th box from the left contains Ai candies.
You will take out the candies from some consecutive boxes and distribute them evenly to M children.
Such being the case, find the number of the pairs (l,r) that satisfy the following:
l and r are both integers and satisfy 1≤l≤r≤N.Al+Al+1+...+Ar is a multiple of M.
Constraints
·All values in input are integers.
·1≤N≤105
·2≤M≤109
·1≤Ai≤109

输入

Input is given from Standard Input in

in the following format:

N M
A1 A2 ... AN

 

输出

Print the number of the pairs (l,r) that satisfy the conditions.
Note that the number may not fit into a 32-bit integer type.
 

样例输入 Copy

3 2
4 1 5

样例输出 Copy

3

提示

The sum Al+Al+1+...+Ar for each pair (l,r) is as follows:
·Sum for (1,1): 4
·Sum for (1,2): 5
·Sum for (1,3): 10
·Sum for (2,2): 1
·Sum for (2,3): 6
·Sum for (3,3): 5
Among these, three are multiples of 2.

[提交][状态]

 

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int> pp;
const int mod=1e6+5;
ll a[mod],sum[mod];
map<ll,ll>mp;

int main()
{
    ll n,m,cnt=0,ans=0;
    scanf("%lld%lld",&n,&m);
    set<ll>vis; //去重
    for(int i=1;i<=n;i++)
    {
       scanf("%lld",a+i);
       sum[i]=sum[i-1]+a[i];
       sum[i]%=m;
       mp[sum[i]]++;
       vis.insert(sum[i]);
    }
    set<ll> ::iterator it=vis.begin(); //指针
    for(; it!=vis.end();it++)
    {
        ll temp=mp[*it];
        ans+=(temp-1)*temp/2;
    }
    ans+=mp[0];
    printf("%lld",ans);
    return 0;
}

 

问题 J: Poll

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

We have N voting papers. The i-th vote (1≤i≤N) has the string Si written on it.
Print all strings that are written on the most number of votes, in lexicographical order.

Constraints
·1≤N≤2×105
·Si (1≤i≤N) are strings consisting of lowercase English letters.
·The length of Si (1≤i≤N) is between 1 and 10 (inclusive).

输入

Input is given from Standard Input in the following format:

N
S1
:
SN

 

输出

Print all strings in question in lexicographical order.

样例输入 Copy

【样例1】
7
beat
vet
beet
bed
vet
bet
beet
【样例2】
8
buffalo
buffalo
buffalo
buffalo
buffalo
buffalo
buffalo
buffalo
【样例3】
7
bass
bass
kick
kick
bass
kick
kick
【样例4】
4
ushi
tapu
nichia
kun

样例输出 Copy

【样例1】
beet
vet
【样例2】
buffalo
【样例3】
kick
【样例4】
kun
nichia
tapu
ushi

提示

样例1解释
beet and vet are written on two sheets each, while beat, bed, and bet are written on one vote each. Thus, we should print the strings beet and vet.

 

思路✔,但是 超时的莫名奇妙,然后学习到了高级技巧

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int> pp;
const int mod=1e5+5;
int A[mod],f[mod];
map<string,int>mp;
int main()
{
  int n,maxn=0;
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
      char str[15];
      scanf("%s",str);
      mp[str]++;
      if(mp[str]>maxn)
        maxn=mp[str];
  }
   map<string,int> ::iterator it=mp.begin(); //指针
    for(; it!=mp.end();it++)
    {
      if((it->second)==maxn)
      cout<<it->first<<endl;
    }
  return 0;
}
 
/**************************************************************
    Problem: 14660
    User: 2019UPC110
    Language: C++
    Result: 时间超限
****************************************************************/

 

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=2e5+5;
string s[mod];
map <string,int> mp;
int main()
{
std::ios::sync_with_stdio(false);
   int n,maxn=0;
  cin>>n;
  for(int i=1;i<=n;i++)
  {
      cin>>s[i];
      mp[s[i]]++;
  }
  for(map<string, int>::iterator it = mp.begin(); it != mp.end(); it++)
        maxn = max(maxn, it->second);
  sort(s+1,s+1+n);
   for(int i=1;i<=n;i++)
   {
       if(mp[s[i]]!=maxn) continue;
         int len=s[i].length();
         for(int j=0;j<len;j++)
            putchar(s[i][j]);
         putchar('\n');
          mp[s[i]]=0;
 
   }
  return 0;
}
 
/**************************************************************
    Problem: 14660
    User: 2019UPC110
    Language: C++
    Result: 正确
    Time:380 ms
    Memory:24012 kb
****************************************************************/

匹配括号 

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stack>
using namespace std;
typedef long long ll;
const int N=50005;
stack<char> q;
int main()
{
    char s[300];
    scanf("%s",s);
    int len=strlen(s);
    for(int i=0; i<len; i++)
    {
        if(s[i]=='['||s[i]=='(')
            q.push(s[i]);
        if(s[i]==']')
        {
            if(q.empty())
            {
                printf("Wrong");
                return 0;
            }
            if(q.top()!='[')
            {
                printf("Wrong");
                return 0;
            }
            q.pop();
        }
        if(s[i]==')')
        {
            if(q.empty())
            {
                printf("Wrong");
                return 0;
            }
            if(q.top()!='(')
            {
                printf("Wrong");
                return 0;
            }
            q.pop();
        }
    }
    if(q.empty()) printf("OK");
    else printf("Wrong");
        return 0;
    }

 

问题 I: 踢石头

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

编程集训,真累人!
课间,某君在操场上沿着笔直的跑道从左往右走着、散步休息……
看到有N个排成一直线的小石头,于是他无聊的踢了起来:
在他遇到第“奇数”块石头时,他会将其往前面踢,能踢多远在输入中会给出,而遇到第“偶数”个石头时不进行处理(不踢:略过)。当有多个石头在同一位置时,则先处理“射程”(踢下,石头往前移的距离)最短的石头。
然后他就这么一直往前走,边走边踢,直到前面已经没有任何石头时,这时候计算该群与出发点的距离。

输入

第一行一个正整数N (0<N<=100,000),表示石头的个数
接下来有N行,每行两个整数,分别表示石头的位置Pi及其射程Di。Pi(0<=Pi<=100,000) 、Di(0<=Di<=1,000)

输出

前面没石头时,离出发点的距离

样例输入 Copy

【样例1】
2
1 5
2 4
【样例2】
2
1 5
6 6

样例输出 Copy

【样例1】
11
【样例2】
12

提示

样例1解析
一开始的时候遇到的是第一个石头(1,5),他的坐标是1,然后往前踢了5个单位之后,坐标变成(6,5) 随后继续往前走,开始遇到第二个石头(2,4),忽略过。 然后继续往前走,遇到了第三个石头(6,5),即原第一个石头,但是它此时坐标为6。往前踢了5个单位之后,坐标变成(11,5), 继续往前走,一直走到坐标11时,遇到第四个石头(11,5),忽略。 前面已经没有石头了,因此此时离坐标原点的距离为11。


在90%的数据中,1 ≤ N ≤ 3000;
在100%的数据中,1 ≤ N ≤ 100000;
保证所有输入数据中等级的值小于10^8,1 ≤ K ≤ N-1 。

[提交][状态]

 自定义结构体优先队列

#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=2e5+5;
map <string,int> mp;
struct node{
  int a;
  int b;
};
struct tem{
    bool operator()(node n, node m){
        if(n.a!=m.a) return n.a>m.a;
        else return n.b>m.b;
    }
 
};
priority_queue<node,vector<node>,tem>q;
int main()
{
  int n;
  scanf("%d",&n);
  while(!q.empty())
    q.pop();
  for(int i=1;i<=n;i++)
  {
      int a,b;
      scanf("%d%d",&a,&b);
      q.push({a,b});
  }
  int cnt=0,ans=0;
  while(!q.empty())
  {
       cnt++;
      int a=q.top().a;
      int b=q.top().b;
      q.pop();
      if(cnt%2==1) {
            q.push({a+b,b});
            ans=max(ans,a+b);
      }
  }
  printf("%d",ans);
    return 0;
}
 
/**************************************************************
    Problem: 15119
    User: 2019UPC110
    Language: C++
    Result: 正确
    Time:53 ms
    Memory:3640 kb
****************************************************************/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值