有点意思的双指针

  day1 当然还学习了双指针,当然效率很高。

这道题很有意思了 数字都是正数。

秒想到了二分 。nlogn 

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=100002;
int T,n,s;
int a[MAXN];
int check(int x)
{
    int maxx=0;
    for(int i=x;i<=n;i++)maxx=max(maxx,a[i]-a[i-x]);
    if(maxx>=s)return 1;
    return 0;
}
int main()
{
    //freopen("1.in","r",stdin);
    T=read();
    while(T--)
    {
        n=read();s=read();
        for(int i=1;i<=n;i++)
        {    
            a[i]=read();
            a[i]+=a[i-1];
        }
        if(a[n]<s){put(0);continue;}
        int l=1,r=n;
        while(l+1<r)
        {
            int mid=(l+r)>>1;
            if(check(mid))r=mid;
            else l=mid;
        }
        if(check(l)==1)put(l);
        else put(r);
    }
    return 0;
}
View Code

但是双指针则可以优化到 O(n);原理是贪心。但是证明 不太会。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=100002;
int T,n,s;
int a[MAXN];
int maxx=0,ans;
int main()
{
    freopen("1.in","r",stdin);
    T=read();
    while(T--)
    {
        n=read();s=read();maxx=0;ans=INF;
        for(int i=1;i<=n;i++)
        {    
            a[i]=read();
            maxx+=a[i];
        }
        if(s==0){put(1);continue;}
        if(maxx<s){put(0);continue;}
        int tmp=0;
        for(int i=0,j=1;j<=n;j++)
        {
            tmp+=a[j];
            while(tmp>=s)ans=min(ans,j-i+1),tmp-=a[i++];
        }
        put(ans);
    }
    return 0;
}
View Code

但是如果元素的值小于0的话 只能前缀和+二分+单调队列了。。。

这很显然是排序后双指针扫描。

但是当前和后面发生碰撞时情况的有两种,设前面指针为i 后面指针为j  且i j相邻

分两种情况:a[i]+a[j]<=s a[i]+a[j]>s;

然后 针对 第一种情况 i+1==j 针对第二种情况 i==j;

对此有三个不同细节的 代码都可解决如下:

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=20002;
int n,s;
int a[MAXN];
int ans,i,j;
int cmp(int x,int y){return x>y;}
int main()
{
    freopen("1.in","r",stdin);
    n=read();s=read();
    for(int k=1;k<=n;k++)a[k]=read();
    sort(a+1,a+1+n,cmp);
    for(i=1,j=n;i<=j;i++)
    {
        while(i<j&&(a[i]+a[j]<=s))j--;
        //找到了一个与a[i] 不匹配的a[j] j+1;
        //n~(j+1) n-(j+1)+1-> n-j;
        //当 i==j时GG 此时匹配成功的还是 j+1
        //此时 再次累加是正确的
        ans+=(n-j);
    }
    j++;
    //cout<<i<<' '<<j<<endl;
    for(int k=j;k<=n;k++)ans+=(n-k);
    put(ans);
    return 0;
}
View Code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=20002;
int n,s;
int a[MAXN];
int ans,i,j;
int cmp(int x,int y){return x>y;}
int main()
{
    freopen("1.in","r",stdin);
    n=read();s=read();
    for(int k=1;k<=n;k++)a[k]=read();
    sort(a+1,a+1+n,cmp);
    for(i=1,j=n;i<=j;i++)
    {
        while(i<j&&(a[i]+a[j]<=s))j--;
        //找到了一个与a[i] 不匹配的a[j] j+1;
        //n~(j+1) n-(j+1)+1-> n-j;
        //当 i==j时GG 此时匹配成功的还是 j+1
        //此时 再次累加是正确的
        ans+=(n-j);
    }
    //cout<<i<<' '<<j<<endl;
    for(int k=i;k<=n;k++)ans+=(n-k);
    put(ans);
    return 0;
}
View Code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define INF 2147483646
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=20002;
int n,s;
int a[MAXN];
int ans,i,j;
int cmp(int x,int y){return x>y;}
int main()
{
    //freopen("1.in","r",stdin);
    n=read();s=read();
    for(int k=1;k<=n;k++)a[k]=read();
    sort(a+1,a+1+n,cmp);
    for(i=1,j=n;i<j;i++)
    {
        while(i<j&&(a[i]+a[j]<=s))j--;
        //找到了一个与a[i] 不匹配的a[j] j+1;
        //n~(j+1) n-(j+1)+1-> n-j;
        //当 i==j时GG 此时匹配成功的还是 j+1
        //此时 再次累加是正确的
        ans+=(n-j);
    }
    //cout<<i<<' '<<j<<endl;
    for(int k=i;k<=n;k++)ans+=(n-k);
    put(ans);
    return 0;
}
View Code

posted @ 2019-02-14 18:33  chdy  阅读(256)  评论(0编辑  收藏  举报