1. 程式人生 > >【UOJ386】【UNR #3】鴿子固定器 鏈表

【UOJ386】【UNR #3】鴿子固定器 鏈表

\n class 次方 print 維護 刪掉 sca clu reverse

題目描述

  有 \(n\) 個物品,每個物品有兩個屬性:權值 \(v\) 和大小 \(s\)

  你要選出 \(m\) 個物品,使得你選出的物品的權值的和的 \(d_v\) 減掉大小的極差的 \(d_s\) 次方最大。

  \(n\leq 200000,m\leq 50,1\leq d_v,d_s\leq 2\)

題解

  如果選的物品的數量不到 \(m\) 個,且不連續,那麽一定不是最優的。

  因為如果不是連續的,那麽可以多選一個大小在這些物品之間的物品,使答案更優。

  如果選了 \(m\) 個物品,那麽可以枚舉權值最小的物品 \(i\),可以發現,選的物品的大小組成了一個包含 \(i\) 的區間。這樣的區間最多只有 \(O(m)\)

個。

  否則可以刪掉 \(i\) 這個物品,換上一個權值更大的物品,使答案更優。

  可以用一個鏈表維護物品的大小組成的序列。

  時間復雜度:\(O(nm)\)

題解

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=200010;
int l[N],r[N];
int n,m,ds,dv;
ll s[N];
ll fp(ll a,int b)
{
    return b==1?a:a*a;
}
ll calc(ll x,ll y)
{
    return fp(x,dv)-fp(y,ds);
}
void del(int x)
{
    r[l[x]]=r[x];
    l[r[x]]=l[x];
}
struct pp
{
    int s,v,c;
};
pp a[N],b[N],c[N];
int cmp1(pp a,pp b)
{
    return a.s<b.s;
}
int cmp2(pp a,pp b)
{
    return a.v<b.v;
}
int t;
ll ans;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    scanf("%d%d%d%d",&n,&m,&ds,&dv);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].s,&a[i].v);
    sort(a+1,a+n+1,cmp1);
    for(int i=1;i<=n;i++)
    {
        a[i].c=i;
        b[i]=a[i];
    }
    for(int i=m;i<=n;i++)
    {
        ll temp=0;
        for(int j=i-m+1;j<=i;j++)
        {
            temp+=a[j].v;
            ans=max(ans,calc(temp,a[j].s-a[i-m+1].s));
        }
    }
    sort(a+1,a+n+1,cmp2);
    for(int i=0;i<=n;i++)
        r[i]=i+1;
    for(int i=1;i<=n+1;i++)
        l[i]=i-1;
    for(int i=1;i<=n;i++)
    {
        t=0;
        for(int j=a[i].c,k=1;j>=1&&k<=m;j=l[j],k++)
            c[++t]=b[j];
        reverse(c+1,c+t+1);
        for(int j=r[a[i].c],k=2;j<=n&&k<=m;j=r[j],k++)
            c[++t]=b[j];
        for(int j=1;j<=t;j++)
            s[j]=s[j-1]+c[j].v;
        for(int j=m;j<=t;j++)
            ans=max(ans,calc(s[j]-s[j-m],c[j].s-c[j-m+1].s));
        del(a[i].c);
    }
    printf("%lld\n",ans);
    return 0;
}

【UOJ386】【UNR #3】鴿子固定器 鏈表