[bzoj4391] [Usaco2015 dec]High Card Low Card 贪心 线段树
题解:
观察到以决策点为分界线,以点数大的赢为比较方式的游戏都是它的前缀,反之以点数小的赢为比较方式的都是它的后缀,也就是答案是由两段答案拼凑起来的。
如果不考虑判断胜负的条件的变化,则有一个比较容易发现的贪心:
设f[i]为从1开始到i位, 比较方式为点数大的获胜,最多能赢几局。
那么为了使答案尽可能优,每次我们都会在剩余牌中找到点数大于对方的 最小的牌,然后出掉。
同理,设g[i]为从n开始到i位,比较方式为点数小的获胜,最多能赢几局,
则每次都在剩余牌中选择点数小于对方的,最大的牌出掉,这样可以使得答案尽可能优。
最后的答案则是max(f[i] + g[i + 1]);
那么为什么这样一定就是合法的呢?
首先最优性应该是可以理解的,那么唯一会导致不合法的情况就是至少一张牌a,在两边的决策中都出现了(即被出掉了2次)。对于这种情况,任意一张a出掉了2次,因为游戏次数=牌数,所以必然还对应着一张b没有被出过。那么如果b > a,则用b来代替f[i]中的a一定合法,因为f[i]是点数大的获胜。反之,b < a, 则用b来代替g[i + 1]中的a一定合法,因为g[i]是点数小的获胜。
于是为了求出这2个数组,我们需要一个可以支持查询前驱后继和删除的数据结构。
你可以选择set,splay,线段树等等。
这里我因为不会用set,懒得写splay,所以选择了值域线段树。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 100100
#define ac 1001000
#define inf INT_MAX int n, w, go, ans;
int tree[ac], maxn[ac], minn[ac], l[ac], r[ac];
int s[AC], f[AC], g[AC];
bool z[AC];//记录哪些牌在对方手里 inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} void pre()
{
n = read();
for(R i = ; i <= n; i ++) s[i] = read(), z[s[i]] = true;
} inline void update(int x)
{
int ll = x * , rr = ll + ;
tree[x] = tree[ll] + tree[rr];
maxn[x] = max(maxn[ll], maxn[rr]);
minn[x] = min(minn[ll], minn[rr]);
} void build(int x, int ll, int rr)
{
l[x] = ll, r[x] = rr;
if(ll == rr)
{
if(!z[ll])
tree[x] = , maxn[x] = ll, minn[x] = ll;
else minn[x] = inf;
return ;
}
int mid = (ll + rr) >> ;
build(x * , ll, mid);
build(x * + , mid + , rr);
update(x);
} void last(int x)//前驱
{
if(minn[x] > w) return ;
if(l[x] == r[x])
{
tree[x] = maxn[x] = , minn[x] = inf, go = ;
return ;
}
if(minn[x * + ] < w) last(x * + );
else last(x * );
update(x);
} void Next(int x)//后继
{
if(maxn[x] < w) return ;
if(l[x] == r[x])
{
tree[x] = maxn[x] = , minn[x] = inf, go = ;
return ;
}
if(maxn[x * ] > w) Next(x * );
else Next(x * + );
update(x);
} void work()
{
build(, , * n);
for(R i = ; i <= n; i ++)
{
w = s[i], go = , Next();
f[i] = f[i - ] + go;
}
build(, , * n);
for(R i = n; i; i --)
{
w = s[i], go = , last();
g[i] = g[i + ] + go;
}
/*for(int i = 1; i <= n; i ++) printf("%d ", f[i]);
printf("\n");
for(int i = 1; i <= n; i ++) printf("%d ", g[i]);
printf("\n");*/
for(R i = ; i <= n; i ++) upmax(ans, f[i] + g[i + ]);
printf("%d\n", ans);
} int main()
{
freopen("in.in", "r", stdin);
pre();
work();
fclose(stdin);
return ;
}
[bzoj4391] [Usaco2015 dec]High Card Low Card 贪心 线段树的更多相关文章
- 【BZOJ4391】[Usaco2015 dec]High Card Low Card(贪心)
[BZOJ4391][Usaco2015 dec]High Card Low Card(贪心) 题面 BZOJ 题解 预处理前缀后缀的结果,中间找个地方合并就好了. #include<iostr ...
- BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库
正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...
- 【题解】P3129高低卡(白金)High Card Low Card
[题解][P3129 USACO15DEC]高低卡(白金)High Card Low Card (Platinum) 考虑贪心. 枚举在第几局改变规则,在改变规则之前,尽量出比它大的最小的牌,在改变规 ...
- 【题解】P1712 [NOI2016]区间(贪心+线段树)
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...
- [BZOJ4391][Usaco2015 dec]High Card Low Card dp+set+贪心
Description Bessie the cow is a huge fan of card games, which is quite surprising, given her lack of ...
- 【dp 贪心】bzoj4391: [Usaco2015 dec]High Card Low Card
巧妙的贪心 Description Bessie the cow is a huge fan of card games, which is quite surprising, given her l ...
- 【刷题】BZOJ 4391 [Usaco2015 dec]High Card Low Card
Description Bessie the cow is a huge fan of card games, which is quite surprising, given her lack of ...
- [USACO15DEC]高低卡(白金)High Card Low Card (Platinum)
题目描述 Bessie the cow is a hu e fan of card games, which is quite surprising, given her lack of opposa ...
- Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)
题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...
随机推荐
- VINS(三)IMU预积分
IMU的数据频率一般远高于视觉,在视觉两帧k,k+1之间通常会有>10组IMU数据.IMU的数据通过积分,可以获取当前位姿(p位置,q四元数表达的姿态).瞬时速度等参数. 在VIO中,如果参考世 ...
- ORB-SLAM(七)ORBextractor 特征提取
该类中主要调用OpenCV中的函数,提取图像中特征点(关键点及其描述,描述子,以及图像金字塔) 参考TUM1.yaml文件中的参数,每一帧图像共提取1000个特征点,分布在金字塔8层中,层间尺度比例1 ...
- Mysql 8.0.* zip版本 windows安装
一,MySQL8.0.*zip版本安装步骤. 1,下载 https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.15-winx64.zip 注现 ...
- SpringBoot入门(四)——自动配置
本文来自网易云社区 SpringBoot之所以能够快速构建项目,得益于它的2个新特性,一个是起步依赖前面已经介绍过,另外一个则是自动配置.起步依赖用于降低项目依赖的复杂度,自动配置负责减少人工配置的工 ...
- pip源设置 & pandas安装
pip的官方源python.pypi.org貌似被墙,换用国内安装源 网上的设置方法都是基于Unix的,Windows下的设置略麻烦. 更新..\Lib\site-packages\pip下的cmdo ...
- Python搭配unittest
unittest是Python的单元测试框架, 类似于Java里面的TestNG. Unittest.py: import unittest from selenium import webdrive ...
- Python常用函数--文档字符串DocStrings
Python 有一个甚是优美的功能称作python文档字符串(Documentation Strings),在称呼它时通常会使用另一个短一些的名字docstrings.DocStrings 是一款你应 ...
- JavaScript 正则
元字符 预定义类 边界 ^在中括号中时,匹配非hello的 str = 'hello world' str.match(/[^hello]/g) //[" ", "w&q ...
- HTML/JSP中一些单书名号标签的用途<%-- --%><!-- --><%@ %><%! %><% %><%= %>
注释 <%-- --%>是(JSP)隐式注释,不会在页面显示的注释 <!-- -->是(Html)显示注释,会在JSP页面显示 关于注释还有单行隐式注释//和多行隐式注释/* ...
- lock+Condition
关键字 synchronized+wait/notify/notifyAll可以实现等待/通知模式,类ReentrantLock可以实现同样的功能,但需要借助Condition对象.Condition ...