1:数组元素的目标和
首先是暴力做法:
暴力做法就是遍历两个数组,如果相加为x,那么就输出这个i和j
然后介绍的是双指针算法
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N],n,m,x;
int main(void)
{
scanf("%d %d %d",&n,&m,&x);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
for(int i=0,j=m-1;i<n;i++)
{
while(a[i]+b[j]>x) j--;
if(a[i]+b[j]==x)
{
printf("%d %d\n",i,j);
}
}
return 0;
}
也可以使用二分查找来解题:依次遍历a数组,然后通过a数组当前的值来反解出来符合条件的值,然后在b数组中看是否可以找到
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N],n,m,x;
int main(void)
{
scanf("%d %d %d",&n,&m,&x);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
for(int i=0;i<n;i++)
{
int y=x-a[i];
int l=0,r=m-1;
while(l<=r)
{
int mid=l+r>>1;
if(b[mid]==y)
{
printf("%d %d",i,mid);
return 0;
}else if(b[mid]<y)
{
l=mid+1;
}else
{
r=mid-1;
}
}
}
return 0;
}
2.区间和
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1000010;
typedef pair<int, int>PII;
vector<PII>query, add;//询问区间还有需要增加的
vector<int>alls;
int a[N], s[N];//s[N]为前缀和
int n, m, l, r, c, x;
int find(int x)
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x)
{
r = mid;
}
else
{
l = mid + 1;
}
}
return l + 1;
}
int main(void)
{
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%d %d", &x, &c);
add.push_back({ x,c });
alls.push_back(x);
}
for (int i = 0; i < m; i++)
{
scanf("%d %d", &l, &r);
query.push_back({ l,r });
alls.push_back(l);
alls.push_back(r);
}
//对所有的区间进行排序,然后进行去重,离散化
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
for (auto tmp : add)
{
int x = find(tmp.first);
a[x] += tmp.second;
}
//求前缀和
for (int i = 1; i <= alls.size(); i++)
{
s[i] = s[i - 1] + a[i];
}
//求区间和
for (auto tmp : query)
{
int l = find(tmp.first), r = find(tmp.second);
printf("%d\n", s[r] - s[l - 1]);
}
return 0;
}
3.双链表
首先我们约定链表头是0,尾是1,这里说的都是下标
所以先对链表进行初始化
然后是插入操作:
删除操作就很简单了:
r[l[k]] = r[k];
l[r[k]] = l[k];
#include<iostream>
using namespace std;
int m;
const int N = 100010;
int e[N], r[N], l[N], idx;
void init()
{
r[0] = 1;
l[1] = 0;
idx = 2;
}
void add(int k, int x)
{
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
idx++;
}
void move(int k)
{
r[l[k]] = r[k];
l[r[k]] = l[k];
}
int main(void)
{
cin >> m;
init();
while (m--)
{
string op;
cin >> op;
int k, x;
if (op == "R")
{
cin >> x;
add(l[1], x);
}
else if (op == "L")
{
cin >> x;
add(0, x);
}
else if (op == "D")
{
cin >> k;
move(k + 1);
}
else if (op == "IL")
{
cin >> k >> x;
add(l[k + 1], x);
}
else {
cin >> k >> x;
add(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i])
{
cout << e[i] << " ";
}
return 0;
}
4:单调栈
暴力解法:从当前位置依次往前遍历,看是否有满足条件的数,有就输出,没有就输出-1
当我们遍历了前面的数,可以利用已知信息来减少遍历次数
思路:
#include<iostream>
using namespace std;
const int N=100010;
int stk[N],m,x,tt;
int main(void)
{
scanf("%d",&m);
while(m--)
{
scanf("%d",&x);
while(stk[tt]>=x&&tt)
{
tt--;
}
if(tt) printf("%d ",stk[tt]);
else printf("-1 ");
stk[++tt]=x;
}
return 0;
}