• 【UOJ386】【UNR #3】鸽子固定器 链表


    题目描述

      有 (n) 个物品,每个物品有两个属性:权值 (v) 和大小 (s)

      你要选出 (m) 个物品,使得你选出的物品的权值的和的 (d_v) 次方减掉大小的极差的 (d_s) 次方最大。

      (nleq 200000,mleq 50,1leq d_v,d_sleq 2)

    题解

      1. 如果选的物品的数量不到 (m) 个,且大小不是连续的,那么一定不是最优的。

      因为如果不是连续的,那么可以多选一个大小在这些物品之间的物品,使答案更优。

      2. 如果选了 (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=1;i<=n;i++)
    	{
    		ll temp=0;
    		for(int j=i;j<=n&&j<=i+m-1;j++)
    		{
    			temp+=a[j].v;
    			ans=max(ans,calc(temp,a[j].s-a[i].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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    ubuntu让脚本在后台运行
    Ubuntu nohup 使用
    ubuntu添加开机启动程序
    ubuntuc查找正在运行的进程
    Python搭建的网站突然缺少包报错
    很杂
    logging模块浅记
    在CentOS 7上安装&配置PostgreSQL 12
    云服务器的centos7桌面版需要安装的应用
    云服务器配置桌面版(windows连接)
  • 原文地址:https://www.cnblogs.com/ywwyww/p/9305901.html
Copyright © 2020-2023  润新知