Comet OJ 三元組 推導+兩個指針+分類討論

題目:https://www.cometoj.com/contest/59/problem/F?problem_id=2681c++

題意:給你n個三元組 ai,bi,ci,若是某一對三元組知足    2*min(ai+aj,bi+bj) <= max(ai+aj,bi+bj),那麼貢獻+ci*cjspa

思路:咱們能夠看的出這個式子其實就是說這個的最大值要是最小值的兩倍,可是咱們不肯定哪一個大指針

咱們就先假設code

2*(ai+aj)<=  bi+bjblog

移項得排序

(2*ai-bi)+(2*aj-bj)<=0ci

那麼咱們按2*ai-bi排序get

咱們能夠得出一個結論,若是當咱們得i與j匹配時,i一定和[i+1,j]都匹配,那麼咱們這裏就能夠記錄一個前綴和,那麼i+1 也一定  是在[i+1,j]這個範圍內找到匹配,it

因此咱們能夠用兩個指針進行查找,這是  ai+aj<=bi+bj的狀況,>的時候咱們只要把ai與bi交換一下就能夠了class

 

#include<bits/stdc++.h>
#define maxn 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
struct sss
{
    ll a,b,c;
}q[maxn];
ll num[maxn];
int n;
int cmp(struct sss x,struct sss y)
{
    return (2*x.a-x.b)<(2*y.a-y.b);
}
ll solve(){
    sort(q,q+n,cmp);
    ll sum=0;
    int l=0,r=n-1;
    num[0]=q[0].c;
    for(int i=1;i<n;i++) num[i]=num[i-1]+q[i].c;
    while(r>=0){
        ll t1=2*q[l].a-q[l].b;
        ll t2=2*q[r].a-q[r].b;
        if(t1+t2<=0) break;
        r--;
    } 
    while(l<=r&&l<n&&r>=0){
        sum=(sum+(num[r]-num[l-1])*q[l].c)%mod;
        l++;
        while(r>=0){
            ll t1=2*q[l].a-q[l].b;
            ll t2=2*q[r].a-q[r].b;
            if(t1+t2<=0) break;
            r--;
        } 
    } 
    return sum;
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lld%lld%lld",&q[i].a,&q[i].b,&q[i].c);
    }
    ll sum=solve();
    //printf("%lld\n",sum);
    for(int i=0;i<n;i++) swap(q[i].a,q[i].b);
    sum=(sum+solve())%mod;
    printf("%lld\n",sum);
} 
相關文章
相關標籤/搜索