牛客IOI周賽20-普及組-D 夾縫中求和(線性優化)

•剪刀石頭布•發表於2020-11-30

在這裡插入圖片描述
輸入

5 2 4
1 4 2 2 1

輸出

6

在這裡插入圖片描述
題意很簡單。
思路:最簡單的直接暴力O(n^2)直接T飛
正解:x-ai<=aj<=y-ai二分查詢aj最小pos和最大pos,然後累加,時間複雜度O(nlogn)

//這個學習別人的解法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int main(){
    ll a, x, y;
    cin >> a >> x >> y;
    vector<ll>v(a);
    for (int i = 0; i < a; i++) cin >> v[i];
    sort(v.begin(), v.end());
    ll ans = 0;
    //x-ai<=aj<=y-ai
    for(int i=0;i<v.size();i++){
        int S = lower_bound(v.begin() + i + 1, v.end(), x - v[i])-v.begin();
        int E = upper_bound(v.begin() + i + 1, v.end(), y - v[i]) - v.begin();
        ans += (E - S);
    }
    cout << ans << endl;
    return 0;
}

隊友寫法,感覺更優秀,省去了一些不必要的計算:隊友真強

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll n,x,y,a[N],ans1,ans2;
int main(){
	scanf("%lld%lld%lld",&n,&x,&y);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	sort(a+1,a+1+n);
	ll l=1,r=n;
	while(l<r){
		while(l<r&&a[l]+a[r]>=x)r--;
		if(l<r)ans1+=r-l;
		l++;
	}
	l=1,r=n;
	while(l<r){
		while(l<r&&a[l]+a[r]>y)r--;
		if(l<r)ans2+=r-l;
		l++;
	}
	cout<<ans2-ans1<<endl;
	return 0;
}

相關文章