本蒟蒻的第一篇题解!!!
式子i−j=ai−aj,可以变式为i−ai=j−aj。
那么对于所有顶点 u,只有u−au相同的才会两两连边。这样整张图就形成了多个联通块。
对于每个联通块,就直接每次找最大值和次大值,把它们包含在答案里即可。 需要注意的是,如果两个点点权之和是负数,就不要选。利用容器动态存储数据,然后对每一个匹配项进行排序求和,求和的时候注意,若两点相加总和小于 0 需要舍弃。
Code:
#include <bits/stdc++.h>
#define int long long
#define IL inline
using namespace std;
IL int read (){
int x=0,f=1;
char ch=getchar ();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar ();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar ();
}
return x*f;
}
IL void white (int x){
if(x<0){
x=-x;
putchar('-');
}
if(x>9)
white(x/10);
putchar(x%10+'0');
}
IL void solve (){
int n;
n=read ();
vector<int>w(n);
for(auto&u:w)
u=read ();
vector<pair<int,int>>v(n);
for(int i=0;i<n;i++)
v[i]={w[i]-i,i};
sort(v.begin(),v.end());
int res=0;
priority_queue<int>q;
for(int i=0;i<n;i++){
if(!i)
q.push(w[v[i].second]);
else
if(v[i].first==v[i-1].first)
q.push(w[v[i].second]);
else{
while(q.size()>=2){
int a,b;
a=q.top(),q.pop(),b=q.top(),q.pop ();
if(a+b>0)
res+=(a+b);
}
while(q.size())
q.pop();
q.push(w[v[i].second]);
}
}
while (q.size()>=2){
int a,b;
a=q.top(),q.pop(),b=q.top(),q.pop();
if(a+b>0)
res+=(a+b);
}
white(res);
puts("");
}
signed main(){
int T;
for(T=read();T;T --)
solve();
return 0;
}