[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)的和. 好难,不会写. ...
随机推荐
- ThinkDev.Data更新日志
2013-09-29 10:001.重构Where.And.Or.Having.JoinTable代码,新增条件组合查询QueryGroup2.1.1.2.0 2013-09-04 09:001.修复 ...
- MySQL☞upper函数
upper(列名/字符串):把小写字母改为大写字母 格式: select upper(列名/字符串) from 表名 如下图:
- 在使用Pipeline串联多个stage时model和非model的区别
train.csv数据: id,name,age,sex1,lyy,20,F2,rdd,20,M3,nyc,18,M4,mzy,10,M 数据读取: SparkSession spark = Spar ...
- Hbase restFul API
获取hbase版本 curl -vi -X GET -H "Accept: text/xml" http://10.8.4.46:20550/version/cluster1.2. ...
- Java基础:关键字final,static
一 . final 含义:adj.最后的,最终的; 决定性的; 不可更改的.在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了 ...
- kvm虚拟化操作
本节演示如何使用 virt-manager 启动 KVM 虚机. 首先通过命令 virt-manager 启动图形界面 # virt-manager 点上面的图标创建虚机 给虚机命名为 kvm1,这里 ...
- IntelliJ IDEA for MAC 注释模板、快捷键生成注释
增加注释 在IntelliJ IDEA中为JAVA代码增加注释,首先需要配置注释模板,而后使用模板快捷键生成注释, 下面按照[配置模板].[模板使用]两部分进行介绍 ----------------- ...
- codeforces 228E The Road to Berland is Paved With Good Intentions(2-SAT)
Berland has n cities, some of them are connected by bidirectional roads. For each road we know wheth ...
- 使用HTML5制作时钟
之前看到别人用HTML5制作时钟,自己也写了一个,这是很久以前写的了,没有注释,现在自己看都晕了(注释的重要性就体现在这边了),找时间加上注释,让自己和别人都比较好理解. <!DOCTYPE h ...
- BluetoothAdapter解析
这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每个常量含义. 一 BluetoothAdapter简介 1.继承关系 该类仅继承了Object类; 2.该类作用 ...