感觉双指针的主要思想就是就是摒弃显然已经被排除的一段
统计和为
k
k
k的子矩阵,枚举区间右端点
r
r
r,当
[
l
,
r
]
[l,r]
[l,r]子段和超过
k
,
l
k,l
k,l右移
因为显然[l,r]不能包含在满足要求的矩阵中(太大了),要缩小,摒弃掉l列以左的所有
双指针分别是区间左右端点
[
l
,
r
]
[l,r]
[l,r],区间数
r
e
s
+
=
(
r
−
l
+
1
)
res+=(r-l+1)
res+=(r−l+1)
Unique Values(序列S中不含重复元素的连续子序列的数量)
这里要求是区间中不含重复元素,当出现重复元素(此时出现在下标i,上一次
m
p
[
a
[
i
]
]
)
mp[a[i]])
mp[a[i]])
要摒弃掉mp[a[i]]以左的元素,有个注意点,
- 1、双指针分别是
l
a
s
t
和
r
last和r
last和r,
l
a
s
t
last
last是上一段满足条件的区间段的最后一个元素,
l a s t last last以左(包含 l a s t last last)已经被摒弃掉了,如果根据 m p mp mp判断出序列中之前有重复元素,
要先判断该元素出现的上一个位置 m p [ a [ i ] ] mp[a[i]] mp[a[i]]是否在 l a s t last last之前,即已经被摒弃掉了
如果已经被摒弃掉了就不需要考虑,否则才要摒弃掉 m p [ a [ i ] ] mp[a[i]] mp[a[i]]及以左所有 - 2、其次区间数 r e s + = ( r − l a s t ) res+=(r-last) res+=(r−last)
#include<bits/stdc++.h>
using namespace std;
#define int long long int
map<int,int>mp;
const int N=1e5+10;
int n;
int a[N];
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int res=0;// 1 2 3 4
int last=0;
for(int i=1;i<=n;i++){
if(mp[a[i]]){
if(mp[a[i]]>last)last=mp[a[i]];
//2 12 3 12 3 2 6 9 遍历到最后一个2,last=第一个3
}
res+=(i-last);//last是上一段满足条件的区间段的最后一个元素
mp[a[i]]=i;
}
cout<<res;
return 0;
}
以下思路是对的,但是求(last,r]这段的子区间数量 方式不对,也不知道为啥不对,给的两个样例也都通过了
不过双指针求区间数量的常见做法都是 每次遍历(一个端点,左指针或右指针)时,利用左右指针相减
#include<bits/stdc++.h>
using namespace std;
#define int long long int
map<int,int>mp;
const int N=1e5+10;
int n;
int a[N];
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int len=0;
int res=n;
int last=0;
for(int i=1;i<=n;i++){
if(mp[a[i]]==0||mp[a[i]]<last){
len++;
mp[a[i]]=i;
}
else{
len=i-mp[a[i]];// 1 2 3 4
res+=(1+len)*len/2-len;
last=mp[a[i]];
mp[a[i]]=i;
}
}
res+=(1+len)*len/2-len;
cout<<res;
return 0;
}