题目大意:
  有一个长度为n的数列,A和B两个人轮流从两端取数,B先取,A想使分数严格小于B且尽量接近B,问两人分数之差最小是多少。

思路:
  折半搜索,先预处理出长度为part的最大差最小差,再预处理出后面一段能取到的不同差值,然后dfs,当范围等于part时,就在数组中二分查找一下。

 #include<cstdio>
#include<cctype>
#include<vector>
#include<ext/hash_set>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int inf=0x7fffffff,_inf=-0x80000000;
const int N=;
int a[N];
int max[N][N],min[N][N],ans,n,part;
inline void init() {
ans=_inf;
for(register int i=;i<=n;i++) {
for(register int j=;j<=n;j++) {
max[i][j]=_inf;
min[i][j]=inf;
}
}
for(register int i=;i<=n;i++) {
max[i][i-]=min[i][i-]=;
}
for(register int i=n;i;i--) {
for(register int j=i;j<=n;j++) {
int l=i,r=j;
int tmp=(a[l]>=a[r])?a[l++]:a[r--];
max[i][j]=std::max(a[l]+max[l+][r],a[r]+max[l][r-])-tmp;
min[i][j]=std::min(a[l]+min[l+][r],a[r]+min[l][r-])-tmp;
}
}
}
std::vector<int> v[N];
__gnu_cxx::hash_set<int> s;
void initPart2() {
part=std::min(,n/);
for(int i=;i<=n+-part*;i++) {
s.clear();
v[i].clear();
for(int j=;j<<<part;j++) {
int tmp=,l=i,r=i+part*-;
for(int k=;k<part;k++) {
tmp-=(a[l]>=a[r])?a[l++]:a[r--];
tmp+=(!(j&(<<k)))?a[l++]:a[r--];
}
if(s.find(tmp)==s.end()) {
s.insert(tmp);
v[i].push_back(tmp);
}
}
std::sort(v[i].begin(),v[i].end());
}
}
void dfs(int l,int r,int dif) {
if(r-l+==part*) {
std::vector<int>::iterator it=std::lower_bound(v[l].begin(),v[l].end(),-dif);
if(it==v[l].begin()&&*it==-dif) return;
if(it==v[l].end()||*it==-dif) it--;
if(dif+*it<) ans=std::max(ans,dif+*it);
return;
}
if(dif+min[l][r]>=) return;
if(dif+max[l][r]<=ans) return;
if(dif+max[l][r]<) {
ans=std::max(ans,dif+max[l][r]);
return;
}
int tmp=(a[l]>=a[r])?a[l++]:a[r--];
dfs(l+,r,dif+a[l]-tmp);
dfs(l,r-,dif+a[r]-tmp);
}
int main() {
getint();
while(~scanf("%d",&n)) {
for(register int i=;i<=n;i++) {
a[i]=getint();
}
init();
initPart2();
dfs(,n,);
if(ans!=_inf) {
printf("%d\n",-ans);
} else {
puts("The child will be unhappy...");
}
}
return ;
}

这段代码在SimpleOJ上交比暴力还慢。

[HDU6196]happy happy happy的更多相关文章

  1. hdu6196 happpy happy happy (meet in middle + 剪枝)

    题意 从1到n共计n(<=90)个物品,每个物品有一个价值a[i],儿子和爸爸轮流做游戏,儿子先手.儿子每次选价值最大的{最左边,最右边}的物品,如果价值一样大, 则选取最左边的物品. 爸爸每次 ...

随机推荐

  1. Interval Minimum Number

    Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. ...

  2. 使用Cache缓存

    存放位置:服务器内存,用于频繁访问且不轻易更改的内容缓存. string CacheKey = "CT1"; //检索指定项, object objModel = Cache.Ge ...

  3. redis从入门到放弃 -> 部署方案

    单点部署方案 环境准备: [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [root@ ...

  4. 缓存数据库-redis数据类型和操作(string)

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合) 一:String(字符串) string是redis ...

  5. java基础46 IO流技术(输出字符流/缓冲输出字符流)

    一.输出字符流 1.1.输出字符流体系 --------| Writer:输出字符流的基类(抽象类)  ----------| FileWriter:向文件输出数据输出字符流(把程序中的数据写到硬盘中 ...

  6. OKR.2019

    转眼又一年过去了,回顾审视一年的得失,规划下一年的奋斗目标.Review And Planning,让全新的2019迎来全新的自己. O1 学习软件开发技术知识 KR1.1 阅读<CLR via ...

  7. 读书笔记--C陷阱与缺陷(四)

    第四章 1. 连接器 C语言的一个重要思想就是分别编译:若干个源程序可在不同的时候单独进行编译,恰当的时候整合到一起. 连接器一般与C编译器分离,其输入是一组目标模块(编译后的模块)和库文件,输出是一 ...

  8. 淘宝开放平台TOP SDK调用对接淘宝或天猫

    如果在淘宝/天猫上开了网店,用户自己也有一套自己的管理平台,这时可能会考虑和淘宝进行数据对接.这就需要考虑调用阿里提供的开发接口来推送和接收数据. 对接的方式有2种,一种是通过http接口,另外一种是 ...

  9. 进程同步——哲学家进餐问题Java实现

    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...

  10. SQLSERVER中的系统存储过程的使用的总结

    -----------------------------系统存储过程-------------------------------- --列出SQL Server实例中的数据库sp_database ...