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;
}