P12996

思路

不会载球跨过原点,数轴两边分开考虑。按距离排序。

可以设 表示 型已经取掉了前 个, 型取掉了前 个。两个相交的同类型匹配不优,可以规定必须转移目前最远端的位置。

只能把两种型号放在一起考虑,设 表示已经取了前 个的最小代价。。

还有一种转移是,设 是 型, 要和之前最近的 型 匹配。此时, 中全为 ,若存在 和 匹配,那可以改为 和 更优。所以 都和 之前的 型匹配。令 为最近的 中两种类型数量相等的位置,在这个区间中可以有后面 匹配前面 的转移,代价为区间中所有 的下标和。

code

int n,c,ans;
int dp[maxn],sum[2][maxn];
int sovle(vector<pii> a){
    int n=a.size();
    a.pb({0,0});sort(a.begin(),a.end());
    unordered_map<int,int> mp;mp[0]=0;
    for(int i=1;i<=n;i++)sum[0][i]=sum[0][i-1],sum[1][i]=sum[1][i-1],sum[a[i].se][i]+=a[i].fi;
    for(int i=1,s=0;i<=n;i++){
        dp[i]=dp[i-1]+2*a[i].fi;
        if(i>=2)dp[i]=min(dp[i],dp[i-2]+2*a[i].fi+(a[i-1].se==a[i].se)*c);
        s+=a[i].se*2-1;
        if(mp.find(s)!=mp.end()){
            int j=mp[s];
            dp[i]=min(dp[i],dp[j]+2*(sum[a[i].se][i]-sum[a[i].se][j]));
        }
        mp[s]=i;
    }
    return dp[n];
}
void work(){
    n=read();c=read();
    vector<pii> a,b;
    for(int i=1;i<=n;i++){
        int x=read(),c=read();
        if(x>0)a.pb({x,c});
        else b.pb({-x,c});
    }
    ans=sovle(a)+sovle(b);
    printf("%lld\n",ans);
}