~~~题面~~~

题解:

  观察到以决策点为分界线,以点数大的赢为比较方式的游戏都是它的前缀,反之以点数小的赢为比较方式的都是它的后缀,也就是答案是由两段答案拼凑起来的。

  如果不考虑判断胜负的条件的变化,则有一个比较容易发现的贪心:

  设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 贪心 线段树的更多相关文章

  1. 【BZOJ4391】[Usaco2015 dec]High Card Low Card(贪心)

    [BZOJ4391][Usaco2015 dec]High Card Low Card(贪心) 题面 BZOJ 题解 预处理前缀后缀的结果,中间找个地方合并就好了. #include<iostr ...

  2. BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库

    正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...

  3. 【题解】P3129高低卡(白金)High Card Low Card

    [题解][P3129 USACO15DEC]高低卡(白金)High Card Low Card (Platinum) 考虑贪心. 枚举在第几局改变规则,在改变规则之前,尽量出比它大的最小的牌,在改变规 ...

  4. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  5. [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 ...

  6. 【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 ...

  7. 【刷题】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 ...

  8. [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 ...

  9. Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)

    题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...

随机推荐

  1. php输出带尖括号的内容

    有这样的数组 $arr = array( 'facebook' => 'facebook', '<facebook>' => '<facebook>', ); 输出 ...

  2. hdu1171Big Event in HDU(01背包)

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. WEB安全--高级sql注入,爆错注入,布尔盲注,时间盲注

    1.爆错注入 什么情况想能使用报错注入------------页面返回连接错误信息 常用函数 updatexml()if...floorextractvalue updatexml(,concat() ...

  4. 180620-mysql之数据库导入导出

    文章链接:https://liuyueyi.github.io/hexblog/2018/06/20/180620-mysql之数据库导入导出/ mysql之数据库导入导出 实际工作中,需要做一下数据 ...

  5. 180609-Spring之事件驱动机制的简单使用

    文章链接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驱动机制的简单使用/ Spring之事件驱动机制的 ...

  6. Web自动化测试环境搭建1(基于firefox火狐浏览器)

    自动化测试是时代趋势,因此很多测试人员开始研究自动化测试,web自动化测试化测试并不难,但是很多人都是被挡在了环境搭建这一步,后面学习激情全无,这里,韬哥手把手教大家搭建火狐浏览器下的自动化测试环境( ...

  7. Python输入数据类型判断正确与否的函数大全(非常全)

      对于python输入数据类型判断正确与否的函数大致有三类: (1)type(),它的作用直接可以判断出数据的类型 (2)isinstance(),它可以判断任何一个数据与相应的数据类型是否一致,比 ...

  8. 初学Direct X (2)

    初学Direct X (2) 这一次要学习如何现实位图,尽管看过对双缓冲机制还有很多疑问,但是这并不阻碍我对他的入门了解 Direct3D提供了一个双重/后台缓冲区,在调用CreateDevice之时 ...

  9. 167. Add Two Numbers【LintCode by java】

    Description You have two numbers represented by a linked list, where each node contains a single dig ...

  10. 技本功丨知否知否,Redux源码竟如此意味深长(上集)

    夫 子 说 元月二号欠下袋鼠云技术公号一篇关于Redux源码解读的文章,转眼月底,期间常被“债主”上门催债.由于年底项目工期比较紧,于是债务就这样被利滚利.但是好在这段时间有点闲暇,于是赶紧把这篇文章 ...