有点意思的双指针
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; }
但是双指针则可以优化到 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; }
但是如果元素的值小于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; }
//#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; }
//#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; }