Educational Codeforces Round 180 (Rated for Div. 2) C. Coloring Game

C -- Coloring Game

思路:不难看出,当 Alice 选完三个数 a b c(其中 a ≤ b ≤ c)后,Bob 能选的只有两种情况:

  1. 选择 c,这样只用比较 a+b 和 c 的大小关系,其中 a+b 一定要大于c;
  2. 选择数组最大值 a[n],这样只用比较 a+b+c 和 a[n] 的大小关系,且前者要更大。
    所以,排序后枚举外层 a_id 和内层 b_id:
  • 对于情况1:因为 a+b 的和一开始较小,后续逐渐变大,所以最大能选择的 c_id 一开始会较小,然后会随着 b_id 的变大而变大,该情况的"最大满足当前条件的 c_id"记为 k;
  • 对于情况2:因为 a+b 的和一开始较小,需要较大的 c 才能使得 a+b+c > a[n],因此满足条件的最小 c_id 一开始会较大,后续随着 a+b 的增大而变小,该情况的"最小满足当前条件的 c_id"记为 l。

那么,对于每对 (a_id, b_id),可选的 c_id 数量即为 [l, k] 区间长度。利用 k、l 单调移动的特点,可用双指针在 O(n²) 内完成。
view code

cpp 复制代码
#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0; rep(i,1,n+1) res=(res+k)%i; return (res+s)%n;}
inline ll read(){ ll f=1,x=0; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f; }
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

ll a[maxn];

void sol() {
    ll n = read();
    rep(i,1,n) a[i] = read();
    sort(a+1,a+1+n);
    ll ans = 0;
    rep(i,1,n) {
        ll k = i+2, l = n;
        rep(j,i+1,n-1) {
            while(k <= n && a[i] + a[j] > a[k]) k++;
            while(l > j && a[i] + a[j] + a[l] > a[n]) l--;
            ll k1 = min(n, k-1), l1 = max(l+1, j+1);
            if(k1 >= l1) ans += (k1 - l1 + 1);
        }
    }
    cout << ans << endl;
}

int main() {
    int kase;
    cin >> kase;
    while(kase--) sol();
    return 0;
}
相关推荐
Closet1231 个月前
Codeforces 2025/6/11 日志
c++·算法·codeforces
maisui121384 个月前
牛客周赛 Round 85
算法·深度优先·codeforces
Sakura176 个月前
Codeforces Round 998 (Div. 3)
codeforces
多思考少编码8 个月前
Codeforces Round 981 (Div. 3) A - E 详细题解(C++)
开发语言·c++·算法·codeforces·算法竞赛
wlwhonest10 个月前
newbie难度——暴力枚举
codeforces·暴力枚举
Aurora_th10 个月前
Codeforces Round (Div.3) C.Sort (前缀和的应用)
c++·算法·前缀和·codeforces·观察力
多思考少编码10 个月前
Codeforces Round 969 (Div. 2) 题ABC详细题解,包含(C++,Python语言描述)
c++·python·算法·codeforces·算法竞赛
QuantAsk1 年前
CF1615H-Reindeer Games【保序回归,整体二分,网络流】
codeforces·网络流·保序回归·整体二分
Aurora_th1 年前
贪心算法的初涉(双指针 + “过山车思想”)
算法·leetcode·codeforces·贪心·双指针·“过山车”思想