zoukankan      html  css  js  c++  java
  • [Luogu] CF557C Arthur and Table

    (Link)

    Description

    有一张桌子,有(n)个腿。第(i)根腿的长度是(l_i)​。

    现在要拿掉一些腿,使得桌子稳定,拿掉第(i)根腿需要(d_i)的能量。

    稳定的条件是,假如拿掉若干条腿之后,桌子还有(k)个腿,那么长度最长的腿的数目要超过一半。比如桌子有(5)根腿,那么至少要有(3)根腿是最长的。另外,只有一根腿的桌子是稳定的,两个腿的桌子想要稳定,必需长度是一样的。

    你的任务是拿掉若干腿,使得桌子稳定,并且所消耗的能量要最少。

    Solution

    我们可以枚举桌腿最长的长度是什么,设其为(l_{mx}),然后有(t)根的(l_i=l_{mx}),那么保留的最大能量就是(sumlimits_{l_i=l_{mx}}d_i),加上长度小于它的桌腿中,选最大的(t-1)根的能量之和(因为要最大化保留的,才能最小化消耗的)。

    考虑我们从小到大枚举(l_{mx}),处理这个长度后再把所有满足(l_i=l_{mx})(d_i)加入当前序列中,那么现在要解决的问题就是要动态维护序列前(t-1)大之和。而对顶堆可以很方便解决这类动态求第(k)大或前(k)大的问题。

    对顶堆就是维护两个堆,一个大根堆(q_1),一个小根堆(q_2),然后保证(q_2)里的所有元素都大于(q_1)里的,不满足就不断一个(pop()),一个(push(top()))

    我们再保证(q_2.size()=t-1),那这道题的前(t-1)大之和就是(q_2)内元素之和了。

    这个是很难被卡的,因为单次操作次数取决于(|t_i-t_{i-1}|),最大也就是(n),复杂度其实和线段树一样也是(nlog(n))

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long
    
    int n, m, sz[100005], l[100005], d[100005];
    
    vector < int > g[100005];
    
    ll mx, s0, sum, s[100005];
    
    priority_queue < int > q1;
    priority_queue < int, vector < int > , greater < int > > q2; 
    
    int read()
    {
    	int x = 0, fl = 1; char ch = getchar();
    	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
    	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    	return x * fl;
    }
    
    int main()
    {
    	n = read();
    	for (int i = 1; i <= n; i ++ )
    		l[i] = read(), m = max(m, l[i]);
    	for (int i = 1; i <= n; i ++ )
    		d[i] = read(), sum += (ll)d[i];
    	for (int i = 1; i <= n; i ++ )
    	{
    		g[l[i]].push_back(d[i]);
    		s[l[i]] += (ll)d[i];
    		sz[l[i]] ++ ;
    	}
    	for (int i = 1; i <= m; i ++ )
    	{
    		if (!sz[i]) continue;
    		ll cnt = s[i];
    		while ((int)q2.size() != sz[i] - 1)
    		{
    			if ((!q1.size()) && (!q2.size())) break;
    			while (q2.size() < sz[i] - 1)
    			{
    				int x = q1.top();
    				q1.pop();
    				q2.push(x);
    				s0 += x;
    			}
    			while (q2.size() > sz[i] - 1)
    			{
    				int x = q2.top();
    				q2.pop();
    				q1.push(x);
    				s0 -= x;
    			}
    		}
    		mx = max(mx, cnt + s0);
    		for (int p = 0; p < (int)g[i].size(); p ++ )
    		{
    			int x = g[i][p];
    			if (q1.size() && x > q1.top()) q2.push(x), s0 += x;
    			else q1.push(x);
    		}
    	}
    	printf("%lld
    ", sum - mx);
    	return 0;
    }
    
  • 相关阅读:
    第六课样式表
    jsp传递参数的四种方法
    Data truncated for column 'Sex' at row 1
    写方法时try,catch 的好处
    访问报错The origin server did not find a current representation for the target resou
    tomcat启动报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost].
    Win10鼠标右键如何添加快捷关机、注销等功能?
    idea tomcat部署
    html如何将图片盖住整个网页
    如果要在标签中显示"<"或者">"等特殊字符,可以使用“&”开头,“;”结尾,中间加上字符对应的编码就可以啦。
  • 原文地址:https://www.cnblogs.com/andysj/p/13961428.html
Copyright © 2011-2022 走看看