CF1857E Power of Points

发布时间 2023-09-08 10:44:12作者: NBest

2023-08-08 22:59:22 CF1857E solution

思路

我们发现每个点的答案其实是它与之前的点的答案加上与后面的点的答案加上与自己的答案。而与前面和与后面的前后缀答案都是可以通过递推的方式得到的,我们令 \(pre_i\) 表示 \(i\) 点的前缀答案,\(sub_i\) 表示 \(i\) 点的后缀答案,\(x_i\) 表示 \(i\) 点的坐标,那么有:

\[pre_i=pre_{i-1}-(x_i-x_{i-1})\times(n-i+1)-1\\ sub_i=sub_{i+1}-(x_{i+1}-x_i)\times i-1 \]

代码有点丑,见谅。

\(Code\)

struct node{
    ll v,id,ans1,ans2;
    inline bool operator <(const node &w)const{
        return v<w.v;
    }
}a[200005];
ll ans[200005];
ll T,n;
int main(){
    for(T=read();T--;){
        n=read();
        for(ll i=1;i<=n;i++){
            a[i].v=read();
            a[i].id=i;
            a[i].ans1=a[i].ans2=0;
        }
        sort(a+1,a+1+n);
        for(ll i=2;i<=n;i++){
            a[1].ans1+=a[i].v-a[1].v+1;
        }
        for(ll i=1;i<n;i++){
            a[n].ans2+=a[n].v-a[i].v+1;
        }
        for(ll i=2;i<n;i++){
            a[i].ans1+=a[i-1].ans1-1ll*(a[i].v-a[i-1].v)*(n-i+1)-1;
        }
        for(ll i=n-1;i>=2;--i){
            a[i].ans2+=a[i+1].ans2-1ll*(a[i+1].v-a[i].v)*i-1;
        }
        for(ll i=1;i<=n;i++)ans[a[i].id]=a[i].ans1+a[i].ans2;
        for(ll i=1;i<=n;i++){
            printf("%lld ",ans[i]+1);
        }
        puts("");
    }
}