【题解】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\)。
我们发现限制不多,可以先去掉限制算出全局的答案,最后再减。
也就是先算出来:
经典起手分类讨论:
- 若 \(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;
}

浙公网安备 33010602011771号