双指针
(又称尺取法)
是一种优化技巧,可用于解决序列的区间问题
两个指针i,j有两种扫描方向
- 反向扫描:i从头到尾,j从尾到头
- 正向扫描:j跑在i前面;也称为快慢指针
连续自然数和
p1147
看作升序,i指针指向一段数字的左边,j指针指向右边。sum为和
如果sum<m,右边边界向右边移动,j++,sum+=j
如果sum>=m,若sum==m,则输出i,j
(P.A:这里不能这样,(下左图))
A-B数对
P1102
用k,i,j三个指针
k指针用于枚举每个数
i指针指向a[i]-a[k]=c的一段数的左端
j指针指向a[i]-a[k]=c的一段数的右端
ans维护这段数的个数,ans+=j-i
点击查看代码
void solve()
{
ll n,c;cin>>n>>c;
ll a[n+10];
for(int i=1;i<=n;++i)
{
cin>>a[i];
}
sort(a+1,a+1+n);
ll i=1,j=1;ll ans=0;
for(ll k=1;k<=n;++k)
{
while(i<=n&&a[i]-a[k]<c) ++i;
while(j<=n&&a[j]-a[k]<=c) ++j;
ans+=j-i;
}
cout<<ans<<'\n';
}
逛画展
注意数组范围哇啊啊,最开始开的是ll a[n+10],cnt[n+10],找不到错误,无能狂怒哇,〒▽〒
点击查看代码
#define ll long long
const ll N=1e6+10;
ll a[N];
ll cnt[2010];
void solve()
{
ll n,m;cin>>n>>m;
for(ll i=1;i<=n;++i)
{
cin>>a[i];
}
ll len; //长度
ll l=0,r=0; //答案左右编号
ll num; //记录当前区间有多少画家
// ll i=1;
cnt[a[1]]=1;num=1;len=INT_MAX;
// cout<<1<<'\n';
for(ll j=1,i=1;j<=n;)
{
if(num<m)
{
j++;
cnt[a[j]]++;
if(cnt[a[j]]==1) num++;
}
if(num==m)
{
if(len>j-i+1)
{
len=j-i+1;
l=i;r=j;
}
cnt[a[i]]--;
if(cnt[a[i]]==0)
{
num--;
}
i++;
}
}
cout<<l<<" "<<r<<'\n';
}

浙公网安备 33010602011771号