传送门

写出来\(n^2\)就有81pts……

\(n^2\)的话枚举最后成为限制的是哪两个矩形,利用前缀和和二分\(n^3\)化\(n^2\)就行了

这题最无脑直接贪心的方法会有后效性

但实际上正解好像就是处理这类问题的一大套路

在两个维度上贪心会有后效性,那选一维枚举,另一维贪心就好了

想了很久也没有想出如何维护\(b_{min}\),题解里说用堆,但用堆我只会\(O(nmlogn)\)复杂度的做法丢人,我暴力都\(O(n^2)\)

思路一直卡在在枚举删\(a_{min}\)的个数时,涉及到在按\(b\)排序的堆中删除\(a\)最小的元素

后来发现不用那么复杂,可以倒序枚举个数,每次加进\(a\)最大的元素

而且堆也没必要每次都清空

发现倒序枚举的实际意义相当于少删一个\(a_{min}\),多删一个\(b_{min}\)

所以维护的时候直接删掉堆里\(b\)最小的,放进去堆外面\(a\)最大的即可

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m;
ll a[N], b[N]; namespace force{
void solve() {
ll ans=0, amin=INF, bmin=INF;
int lim=1<<n;
for (int s=0,s2,cnt; s<lim; ++s) {
s2=s; cnt=0; amin=INF, bmin=INF;
while (s2) {++cnt; s2&=s2-1;}
if (cnt>m) continue;
for (int i=0; i<n; ++i) {
if (!(s&(1<<i))) {
amin=min(amin, a[i+1]);
bmin=min(bmin, b[i+1]);
}
}
ans=max(ans, amin*bmin);
}
printf("%lld\n", ans);
}
} namespace task1{
void solve() {
sort(b+1, b+n+1);
printf("%lld\n", a[1]*b[m+1]);
}
} namespace task2{
void solve() {
ll amin=INF, bmin=INF;
for (int i=1; i<=n; ++i) amin=min(amin, a[i]), bmin=min(bmin, b[i]);
printf("%lld\n", amin*bmin);
}
} namespace task3{
void solve() {
ll ans=0;
for (int i=1; i<=n; ++i) ans=max(ans, a[i]*b[i]);
printf("%lld\n", ans);
}
} namespace task4{
struct rat{ll a, b; inline void build(ll a_, ll b_) {a=a_; b=b_;}}p[N];
inline bool operator < (rat a, rat b) {return a.a==b.a?a.b<b.b:a.a<b.a;}
ll b2[N];
void solve() {
int tot, dlt; ll ans=0;
for (int i=1; i<=n; ++i) p[i].build(a[i], b[i]);
sort(p+1, p+n+1);
for (int i=1; i<=min(n, m+1); ++i) {
//cout<<"i: "<<i<<endl;
tot=0; dlt=i-1;
for (int j=i+1; j<=n; ++j) if (p[j].b<p[i].b) b2[++tot]=p[j].b;
sort(b2+1, b2+tot+1);
if (dlt+tot<=m) ans=max(ans, p[i].a*p[i].b);
//cout<<"tot: "<<tot<<' '<<dlt<<endl;
//cout<<"b2: "; for (int j=1; j<=tot; ++j) cout<<b2[j]<<' '; cout<<endl;
for (int j=i+1,t; j<=n; ++j) {
t = lower_bound(b2+1, b2+tot+1, p[j].b)-b2-1;
//cout<<"t: "<<t<<endl;
if (dlt+t>m) continue;
else ans=max(ans, p[i].a*min(p[i].b, p[j].b));
//cout<<"upd: "<<i<<' '<<j<<' '<<p[i].a*min(p[i].b, p[j].b)<<endl;
}
//cout<<"ans: "<<ans<<endl<<endl;
}
printf("%lld\n", ans);
}
} namespace task5{
struct rat{ll a, b; inline void build(ll a_, ll b_) {a=a_; b=b_;}}p[N];
inline bool operator < (rat a, rat b) {return a.a==b.a?a.b<b.b:a.a<b.a;}
struct ele{ll a, b; ele(ll a_, ll b_):a(a_),b(b_){} ele(){}};
inline bool operator < (ele a, ele b) {return a.b>b.b;}
priority_queue<ele> q;
void solve() {
//if (n==1) {printf("%lld\n", a[1]*b[1]); return ;}
for (int i=1; i<=n; ++i) p[i].build(a[i], b[i]);
//for (int i=1; i<=n; ++i) cout<<p[i].a<<','<<p[i].b<<endl;
sort(p+1, p+n+1);
ll ans=0, amin=INF, bmin=INF;
for (int i=0; i<=m; ++i) {
//cout<<"i: "<<i<<endl;
amin=INF, bmin=INF;
for (int j=i+1; j<=n; ++j) q.push(ele(p[j].a, p[j].b));
for (int j=i+1; j<=m; ++j) q.pop();
while (!q.empty()) {amin=min(amin, q.top().a); bmin=min(bmin, q.top().b); q.pop();}
//cout<<"min: "<<amin<<' '<<bmin<<endl;
ans=max(ans, amin*bmin);
}
printf("%lld\n", ans);
}
} namespace task{
struct rat{ll a, b; inline void build(ll a_, ll b_) {a=a_; b=b_;}}p[N];
inline bool operator < (rat a, rat b) {return a.a==b.a?a.b<b.b:a.a<b.a;}
priority_queue< int, vector<int>, greater<int> > q;
void solve() {
//if (n==1) {printf("%lld\n", a[1]*b[1]); return ;}
for (int i=1; i<=n; ++i) p[i].build(a[i], b[i]);
//for (int i=1; i<=n; ++i) cout<<p[i].a<<','<<p[i].b<<endl;
sort(p+1, p+n+1);
ll ans=0;
while (!q.empty()) q.pop();
for (int i=m+1; i<=n; ++i) q.push(p[i].b);
for (int i=m+1; i; --i) {
ans=max(ans, p[i].a*q.top());
q.pop(); q.push(p[i-1].b);
}
printf("%lld\n", ans);
}
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
int T; T=read();
if (!T) return 0;
while (T--) {
bool equal=1;
n=read(); m=read();
for (int i=1; i<=n; ++i) {
a[i]=read(), b[i]=read();
if (i!=1) {if (a[i]!=a[i-1]) equal=0;}
}
//if (0&&n<=25) force::solve();
//else if (!m) task2::solve();
//else if (equal) task1::solve();
//else if (m==n-1) task3::solve();
//else task4::solve();
task::solve();
} return 0;
}

题解 d的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. 不同版本docker修改存储位置补充

    前言:最近发现yum安装docker,安装的版本不一样,有点蛇皮,虽然存放默认位置都是/var/lib/docker,但是它的配置文件不一样,这里做个补充 对于docker版本是1.13及以下 操作如 ...

  2. 必须要了解的Linux基本操作

    Linux常用的基础操作             1.命令行提示字符             2.切换用户             3.查看当前主机的完整名称             4.临时设置主机 ...

  3. Guava Cache使用的三种姿势

    姿势一 使用expiredAferWriter 优点 简单 粗暴 缺点 同步阻塞问题:如果多个线程同时请求同一个过期的key,只有一个线程能够获得去加载缓存的锁,但是其他未获取加载缓存锁的线程也会阻塞 ...

  4. box-shadow详解

    今天课堂上有学生问到box-shadow这个属性,那么下面我们就来详细的解说下这个属性它的用法,box-shadow是css3中的一个属性,它可以向框添加一个或多个阴影. 首先我们来看它的语法: bo ...

  5. git的一些常用基础命令

    一些常用的git命令操作简单总结 记录常用的git命令,附带命令的简单使用说明 git区域分布 remote远程仓库 repository本地仓库 index暂存区 workspace工作区 stas ...

  6. [考试总结]noip模拟7

    为啥博客园 \(\LaTeX\) 老挂???! \(\huge{\text{菜}}\) 刚开始写 \(T1\) 的时候,在看到后缀前缀之后,直接想到 \(AC\) 自动机,在画了半个 \(trie\) ...

  7. 生成python 依赖文件

    1.生成requirement 文件的两种方式 1. 'pip freeze ' > requirements.txt --会将环境中的依赖包全都加入(不推荐) 2. 项目用到生成依赖 '# 安 ...

  8. 什么是ETL--ETL定义、过程和工具选型思路

    ETL代表"提取.转换和加载".ETL 过程在数据集成策略中起着关键作用.ETL允许企业从多个来源收集数据并将其整合到一个集中的位置.ETL还使不同类型的数据可以协同工作. 概述 ...

  9. 犀牛Rhino 7.0中文版安装破解教程

    犀牛Rhino 7.0中文版是一款专业的.功能强大的三维建模软件,利用它可以创建.编辑.分析.提供.渲染.动画与转换NURBS线条.曲面.实体与多边形网格:它能轻易整合3DS MAX 与Softima ...

  10. K-Fold 交叉验证

    转载--原文地址 www.likecs.com 1.K-Fold 交叉验证概念 在机器学习建模过程中,通行的做法通常是将数据分为训练集和测试集.测试集是与训练独立的数据,完全不参与训练,用于最终模型的 ...