【题解】CF1043E Train Hard, Win Easy

题目翻译可能有点难理解(总之笔者是花费了一点时间)。

简要题意:

给定 \(n\) 个人的属性 \((a_i,b_i)\)\(m\) 个限制,每个限制 \(u_i,v_i\) 表示 \(u_i\) 不能与 \(v_i\) 配对。接下来将整数 \(i\isin [1,n]\) 与整数 \(j\isin [1,n],i\neq j\) 配对,每个合法的配对的得分为 \(\min(a_i+b_j,a_j+b_i)\)。求出每个人的所有合法的配对的得分之和。(注:输出 \(n\) 个数)
其中,\(2\leq n\leq 3\times 10^5,0\leq m\leq 3\times 10^5,-10^9\leq a_i,b_i\leq 10^9,1\leq u_i,v_i\leq n,u_i\neq v_i\)

我们发现限制不多,可以先去掉限制算出全局的答案,最后再减。
也就是先算出来:

\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n} \min(a_i+b_j,a_j+b_i) \]

经典起手分类讨论:

  • \(a_i+b_j<a_j+b_i\),也即 \(a_i-b_i<a_j-b_j\),则 \(\min\) 值为 \(a_i+b_j\)
  • \(a_i+b_j\geq a_j+b_i\),也即 \(a_i-b_i\geq a_j-b_j\),则 \(\min\) 值为 \(a_j+b_i\)

(解释一下:为什么要把与 \(i\) 有关的移到一边?因为方便观察)

以第 \(1\) 种情况举例,发现 \(a_i\) 这部分是可以直接算的啊,先不管。
剩下的 \(b_j\) 可以用 SGT(线段树)或者 BIT(树状数组)维护权值和,那么直接值域 SGT。
大致做法:
枚举 \(i\),通过数据结构查询。当然了要分类讨论(上述 \(2\) 种情况)。
(如果看不懂可以看代码,可能比文字更容易理解)

上面提到,\(a_i\) 部分还没算。
再用一棵 SGT 维护值域内数的出现次数。若查询结果为 \(res\),则 \(a_i\) 部分的和就是 \(a_i\times res\)

\(2\) 种情况同理哦。

最后遍历一下记录的 \(m\) 个限制的 \(vector\),减去得分即可。

高兴地实现。
然而改了相当一段时间后的 评测结果 以及计算器的计算结果告诉我们,空间要炸。
于是改用离散化,具体的:将 \(a_i-b_i\) 离散化,然后就能用 BIT 维护了。
这个故事告诉我们要算好空间再用 SGT。。

比完赛发现排序可以快速处理,没必要用数据结构。
不管了不管了,能过就行。

Code

#include<bits/stdc++.h>

typedef int IT;
typedef long long LL;
typedef __int128 int128;
typedef double DB;
typedef long double LDB;

#define pb push_back
#define fst first
#define sec second
#define psh push
#define mkp make_pair
#define PII pair<IT,IT>
#define PLI pair<LL,IT>
#define lowbit(x) ((x)&(-x))

using namespace std;

const int N=3e5+10;
const LL V=4e9+20,DEL=2e9+1,LOGV=32;// ,LOGV=30;// 36;
const int TOTP=5.2e6;

int n,m;
int a[N],b[N];

vector<int>hate[N];// hate

int lshcnt;
unordered_map<int,int>rk;
// struct lshaaa{
//     int val;
//     int id;
// }lsh[N];
// bool cmp(node x,node y){
//     return x.val<y.val;
// }
int lsh[N];

struct BITQWQ{
    LL t[N];

    void update(int x,LL del){
        for(;x<=lshcnt;x+=lowbit(x)) t[x]+=del;
        return;
    }
    LL query(int x){
        LL res=0;
        for(;x;x-=lowbit(x)) res+=t[x];
        return res;
    }
}T1,T2,T3;

LL ans[N];

int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&a[i],&b[i]);
        lsh[i]=a[i]-b[i];
    }
    // sort(lsh+1,lsh+n+1,cmp);
    sort(lsh+1,lsh+n+1);
    lshcnt=unique(lsh+1,lsh+n+1)-(lsh+1);
    for(int i=1;i<=n;i++){
        // int id=lsh[i].id;
        // rk[a[id]-b[id]]=lower_bound(lsh+1,lsh+n+1)
        int c=a[i]-b[i];
        rk[c]=lower_bound(lsh+1,lsh+lshcnt+1,c)-lsh;
    }
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d %d",&u,&v);
        hate[u].pb(v),hate[v].pb(u);
    }

    for(int i=1;i<=n;i++){
        // T1.modify(T1.rot,1,V,(LL)a[i]-b[i]+DEL,a[i]);
        // T3.modify(T3.rot,1,V,(LL)a[i]-b[i]+DEL,1);
        // T2.modify(T2.rot,1,V,(LL)a[i]-b[i]+DEL,b[i]);

        T1.update(rk[a[i]-b[i]],a[i]);
        T3.update(rk[a[i]-b[i]],1);
        T2.update(rk[a[i]-b[i]],b[i]);
    }

    for(int i=1;i<=n;i++){
        // ans[i]+=T1.query(T1.rot,1,V,1,(LL)a[i]-b[i]+DEL);
        // ans[i]+=T2.query(T2.rot,1,V,(LL)a[i]-b[i]+1+DEL,V);

        ans[i]+=T1.query(rk[a[i]-b[i]]);
        ans[i]+=T2.query(lshcnt)-T2.query(rk[a[i]-b[i]]+1-1);

        // LL res=T3.query(T3.rot,1,V,1,(LL)a[i]-b[i]+DEL);
        LL res=T3.query(rk[a[i]-b[i]]);
        ans[i]+=res*b[i];
        ans[i]+=(n-res)*a[i];

        for(int j=0,len=hate[i].size();j<len;j++){
            int nwa=a[hate[i][j]],nwb=b[hate[i][j]];
            ans[i]-=min(nwa+b[i],nwb+a[i]);
        }
        ans[i]-=(a[i]+b[i]);
    }

    for(int i=1;i<=n;i++) printf("%lld ",ans[i]);putchar('\n');
    return 0;
}

Link

posted @ 2025-12-24 22:46  YuYuanPQ  阅读(0)  评论(0)    收藏  举报