zoukankan      html  css  js  c++  java
  • uoj #386. 【UNR #3】鸽子固定器

    题目描述

    为了固定S**p*鸽鸽,whx和zzt来到鸽具商店选购鸽子固定器。

    鸽具商店有(n)个不同大小的固定器,现在可以选择至多(m)个来固定S**p*鸽鸽。每个固定器有大小(s_i)和牢固程度(v_i)

    如果他们选购的固定器大小不一或是不牢固,固定S**p*鸽鸽的时候肯定会很头疼,所以定义选择的物品总牢固程度和的(dv)次方减大小极差的(ds)次方为这个方案的价值,求不同选购方案中,价值的最大值。

    题解

    题目相当于让求(max((sum v_i)^{dv} - (max(s_i) - min(s_i))^{ds})),对于减号的后面部分我们可以考虑将每个固定器以结构体存下来并将它们按照(s_i)从小到大排序,那么每次选的数的最左端和最右端就是(min)(max)

    然后考虑前半部分,区间长度(leq m)的区间显然暴力处理就好,那么考虑如果一个区间长度(>m)呢?

    我们发现,区间长度(>m)的话一定是选择(m)个数是最优的,而且选择的一定是这段区间(v_i)最大的(m)个数,考虑我们还要满足(s_i)的条件,也就是说要满足左右端点的(s_i)分别最大最小,所以说我们需要保证(s_i)的顺序不能乱,同时这(m)个固定器的(v_i)是最大的。

    所以可以用链表来维护,将固定器按照(v_i)从小到大依次去除,这样的话留下的连着的(m)个数一定是一段区间中(v_i)最大的(m)个数,每次用去除的数和它的的左右部分更新一下答案就可以统计到它的贡献了。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #define ll long long
    using namespace std;
    const int N = 2e5 + 5;
    int n, m, ds, dv, nex[N], last[N], id[N], sta[N], top;
    ll ans, sum[N];
    struct node{int s, v;}a[N];
    inline 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 << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    ll calcv(ll x) {return dv == 1 ? x : x * x;}
    ll calcs(ll x) {return ds == 1 ? x : x * x;}
    bool cmp1(const node & a, const node & b) {return a.s < b.s;}
    bool cmp2(const int & x, const int & y) {return a[x].v < a[y].v;}
    void work()
    {
    	n = read(); m = read(); ds = read(); dv = read();
    	for(int i = 1; i <= n; i ++) {a[i].s = read(); a[i].v = read();}
    	sort(a + 1, a + n + 1, cmp1);
    	for(int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i].v;
    	for(int l = 1; l <= n; l ++)
    		for(int r = l; r <= min(l + m - 1, n); r ++)
    			ans = max(ans, calcv(sum[r] - sum[l - 1]) - calcs(a[r].s - a[l].s));
    	for(int i = 1; i <= n; i ++) id[i] = i;
    	for(int i = 1; i < n; i ++) nex[i] = i + 1, last[i + 1] = i;
    	sort(id + 1, id + n + 1, cmp2);
    	for(int i = 1; i <= n; i ++)
    	{
    		int x = id[i]; top = 0;
    		for(int p = last[x], j = 1; j < m && p; p = last[p], j ++) sta[++ top] = p;
    		reverse(sta + 1, sta + top + 1); sta[++ top] = x;
    		for(int p = nex[x], j = 1; j < m && p; p = nex[p], j ++) sta[++ top] = p;
    		for(int j = 1; j <= top; j ++) sum[j] = sum[j - 1] + a[sta[j]].v;
    		for(int j = m; j <= top; j ++) ans = max(ans, calcv(sum[j] - sum[j - m]) - calcs(a[sta[j]].s - a[sta[j - m + 1]].s));//区间长度小于m的肯定是不优的,就不用统计了
    		nex[last[x]] = nex[x]; last[nex[x]] = last[x];
    	}
    	printf("%lld
    ", ans);	
    }
    int main() {return work(), 0;}
    
  • 相关阅读:
    form2js的使用(续BootstrapTable)
    input限定文件上传类型:Microsoft Office MIME types
    Zookeeper环境搭建
    Zookeeper一致性协议——ZAB
    Zookeeper简介
    IOC容器加载流程
    Spring Bean 生命周期
    Spring Framework 5 模块组成、体系结构、整体架构
    什么是 IoC?什么是 DI ? 他们之间有什么关系?
    【MySQL实战45讲】索引部分整理
  • 原文地址:https://www.cnblogs.com/Sunny-r/p/12587532.html
Copyright © 2011-2022 走看看