ABC127

ABC127 D

题目大意:

给定数字\(a_1\sim a_n\),有\(m\)次顺序操作,每次可以将最多\(b_i\)张牌变成\(c_i\),求\(m\)次操作后卡牌上最大总点数和的情况

题解:

挺新奇的思路,将\(n\)张牌和\(\sum_{i=1}^{m}b_i\)张牌全部丢进去,取最大的\(n\)张牌出来

不用实际丢进去,只要一个归并排序的合并方法就可以

ABC127 E

题目大意:

\(n*m\)的棋盘中选择\(k\)个点,一种方法的贡献是\(k\)个点中两两曼哈顿距离之和,求所有方案的贡献和

\(n*m\leq 2e5\)

题解:

对于一种选择方案,贡献是:

\[\sum_{i=1}^{k-1}\sum_{j=i+1}^k|x_i-x_j|+|y_i-y_j| \]

显然我没发现\(x,y\)可以分开讨论,我们以讨论\(x\)的贡献为例

一种好出的想法是枚举两个点的\(x\)坐标造成的贡献,然后其他点任意选择

\[\sum_{i=1}^{n-1}\sum_{j=1}^{n}|i-j|*m^2*\dbinom{n*m-2}{k-2} \]

这样复杂度无法接受,但是其实只要枚举\(|i-j|\)就可以了,设\(d=|i-j|\)

\[\sum_{d=1}^{n-1}d*(n-d)*m^2*\dbinom{n*m-2}{k-2} \]

ABC127 F

题目大意:

有一个函数\(f(x)\),初始时\(f(x)=0\)

有两种操作:

第一种:\(f(x)=f(x)+|x-a|+b\)

第二种:求令\(f(x)\)最小的\(x\)\(f(x)\)的最小值

题解:

每个\(b\)的独立计算的,只要求\(x_0\)使得\(\sum_{i}|x_0-a_i|\)最小

等价于动态求中位数

学到了一种看上去很牛逼的对顶堆写法,超短

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define mid ((l+r)>>1)
#define eps (1e-12)
	inline int read()
	{
		int x=0;char ch,f=0;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=1,ch=getchar();
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
		return f?-x:x;
	}
	const int N=5e5+10,mod=1e9+7;
	int n,sum;
	priority_queue<int,vector<int>,greater<int> > q2;
	priority_queue<int> q1;
	inline void main()
	{
		n=read();
		for(int opt,x,y,i=1;i<=n;++i)
		{
			opt=read();
			if(opt==1)
			{
				x=read(),y=read();
				sum+=y;
				q1.push(x);q2.push(x);
				int l=q1.top();q1.pop();
				int r=q2.top();q2.pop();
				if(l>r){sum+=l-r;swap(l,r);}
				q1.push(l);q2.push(r);
			}
			else
			{
				
				printf("%lld %lld\n",q1.top(),sum);
			}
		}
	}
}
signed main()
{
	red::main();
	return 0;
}
原文地址:https://www.cnblogs.com/knife-rose/p/15694982.html