数组下标大奥秘

杰哥的疑问

题目
杰哥给出了一个数m。杰哥想知道,这个数组中有多少对数的和等于给定的数。

即有多少对 (i,j)满足 ai+aj=m,且1 <=i < j <= n。

输入描述:
第一行输入两个正整数 n,m 分别表示数组的元素个数,以及杰哥给定的数。(1≤n≤10^6, 0≤m≤10^9)

第二行输入 n 个正整数,第 i 个正整数为 ai(0≤ai≤10^9)。

输出描述:
输出一行一个正整数,表示满足条件的对的数量。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
unordered_map<int, int> mp;
int n, m;

int main(){
	cin >> n >> m;
	ll res = 0;
	for(int i = 1; i<=n; i++){
		int x; cin >> x;
		res += mp[m-x];
		mp[x]++;
	}	
	cout << res;
	return 0;
}

单调队列——滑动窗口

题目:

给定一个大小为 n≤10^6 的数组。

有一个大小为 k 的滑动窗口,它从数组的最左边移动到最右边。

你只能在窗口中看到 k 个数字。

每次滑动窗口向右移动一个位置。

求每个窗口中数的最大值和最小值。

输出描述:

输出两行,第一行输出所有窗口的最小值,第二行输出最大值。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+6;
int a[N];
int q[N]; // 记录的是下标
int tt, hh, n, k;

int main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> k;
    for(int i = 0; i < n; i++)cin >> a[i];
    hh = 0, tt = -1; //用数组模拟队列,tt从-1开始则当前的tt是有值的
    for(int i = 0; i < n; i++){
        if(hh <= tt && i-k+1 > q[hh]) hh++;//判断队头是否该滑出窗口
        while(hh <= tt && a[q[tt]] >= a[i]) tt--;
        q[++tt] = i;
        if(i >= k-1)cout << a[q[hh]] << " ";
    }
    cout << '\n';

    hh = 0, tt = -1;
    for(int i = 0; i < n; i++){
        if(hh <= tt && i-k+1 > q[hh]) hh++;
        while(hh <= tt && a[q[tt]] <= a[i]) tt--;
        q[++tt] = i;
        if(i >= k-1)cout << a[q[hh]] << " ";
    }
    cout << '\n';

    return 0;
}
posted @ 2022-07-22 10:46  每日一题,医生远离  阅读(46)  评论(0)    收藏  举报