题目大意:
  给你一个数列,问区间[l,r]内与k最接近的数与k的差是多少。

思路:
  将数列中的数和询问的数先从小到大排序,
  从小到大枚举每个数,如果是数列上的,就加到线段树中,
  如果是询问中的,就在线段树上查找区间最大值,
  这样就找到了区间中小于等于这个数的最大值。
  反过来也一样。
  一个最大值、一个最小值,对于询问的数作差,取min即可。
  比原来的主席树算法不知道妙到哪里去了。
  主席树加了离散化以后应该能过,不过我的程序一直没过,然而虞皓翔同样是主席树的程序可以随便过。
  大概是我写得比较烂吧。

 #include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#include<functional> 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;
const int N=; struct Num {
int val,pos,l,r,id;
bool operator < (const Num &another) const {
if(val<another.val) return true;
if(val>another.val) return false;
return pos;
}
bool operator > (const Num &another) const {
if(val>another.val) return true;
if(val<another.val) return false;
return pos;
}
};
std::vector<Num> v; class SegmentTree {
#define _left <<1
#define _right <<1|1
private:
int val[N<<];
void push_up(const int &p,const bool &cmp) {
val[p]=cmp?std::max(val[p _left],val[p _right]):std::min(val[p _left],val[p _right]);
}
public:
void reset(const int &x) {
std::fill(&val[],&val[N<<],x);
}
void modify(const int &p,const int &b,const int &e,const int &x,const int &v,const bool &cmp) {
if(b==e) {
val[p]=v;
return;
}
const int mid=(b+e)>>;
if(x<=mid) modify(p _left,b,mid,x,v,cmp);
if(x>mid) modify(p _right,mid+,e,x,v,cmp);
push_up(p,cmp);
}
int query(const int &p,const int &b,const int &e,const int &l,const int &r,const bool &cmp) {
if(b==l&&e==r) {
return val[p];
}
const int mid=(b+e)>>;
int ret=cmp?-:inf;
if(l<=mid) ret=cmp?std::max(ret,query(p _left,b,mid,l,std::min(mid,r),cmp)):std::min(ret,query(p _left,b,mid,l,std::min(mid,r),cmp));
if(r>mid) ret=cmp?std::max(ret,query(p _right,mid+,e,std::max(mid+,l),r,cmp)):std::min(ret,query(p _right,mid+,e,std::max(mid+,l),r,cmp));
return ret;
}
#undef _left
#undef _right
};
SegmentTree t; int ans[N]; int main() {
int T=getint();
for(register int i=;i<=T;i++) {
printf("Case #%d:\n",i);
const int n=getint(),q=getint();
v.clear();
for(register int i=;i<=n;i++) {
v.push_back((Num){getint(),i,,,});
}
for(register int i=;i<q;i++) {
const int l=getint(),r=getint(),k=getint();
v.push_back((Num){k,,l,r,i});
}
std::fill(&ans[],&ans[q],inf);
t.reset(-);
std::sort(v.begin(),v.end(),std::less<Num>());
for(register std::vector<Num>::iterator it=v.begin();it!=v.end();it++) {
if(it->pos) {
t.modify(,,n,it->pos,it->val,true);
} else {
const int tmp=t.query(,,n,it->l,it->r,true);
if(tmp!=-) ans[it->id]=std::min(ans[it->id],std::abs(tmp-it->val));
}
}
t.reset(inf);
std::sort(v.begin(),v.end(),std::greater<Num>());
for(register std::vector<Num>::iterator it=v.begin();it!=v.end();it++) {
if(it->pos) {
t.modify(,,n,it->pos,it->val,false);
} else {
const int tmp=t.query(,,n,it->l,it->r,false);
if(tmp!=inf) ans[it->id]=std::min(ans[it->id],std::abs(tmp-it->val));
}
}
for(register int i=;i<q;i++) {
printf("%d\n",ans[i]);
}
}
return ;
}

原来也写过一个主席树的写法,然而复杂度不是很优秀,一直过不了。

 #include<cstdio>
#include<cctype>
#include<algorithm>
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;
const int N=;
int size;
class FotileTree {
private:
struct Node {
int left,right,val;
};
Node nd[N*];
int sz,newNode(const int &p) {
sz++;
nd[sz]=nd[p];
return sz;
}
public:
int root[N];
void reset() {
sz=;
}
int modify(const int &p,const int &b,const int &e,const int &x) {
int new_p=newNode(p);
nd[new_p].val++;
if(b==e) return new_p;
const int mid=(b+e)>>;
if(x<=mid) nd[new_p].left=modify(nd[p].left,b,mid,x);
if(x>mid) nd[new_p].right=modify(nd[p].right,mid+,e,x);
return new_p;
}
int queryleq(const int &p1,const int &p2,const int &b,const int &e,const int &x) const {
if(!(nd[p2].val-nd[p1].val)) return size-;
if(b==e) return e;
const int mid=(b+e)>>;
if(x<=mid) return queryleq(nd[p1].left,nd[p2].left,b,mid,x);
int ret;
if((ret=queryleq(nd[p1].right,nd[p2].right,mid+,e,x))!=size-) return ret;
if((ret=queryleq(nd[p1].left,nd[p2].left,b,mid,x))!=size-) return ret;
return size-;
}
int querygeq(const int &p1,const int &p2,const int &b,const int &e,const int &x) const {
if(!(nd[p2].val-nd[p1].val)) return size-;
if(b==e) return b;
const int mid=(b+e)>>;
if(x>mid) return querygeq(nd[p1].right,nd[p2].right,mid+,e,x);
int ret;
if((ret=querygeq(nd[p1].left,nd[p2].left,b,mid,x))!=size-) return ret;
if((ret=querygeq(nd[p1].right,nd[p2].right,mid+,e,x))!=size-) return ret;
return size-;
}
};
FotileTree t;
int a[N],l[N],r[N],x[N],b[N+N];
int main() {
int T=getint();
for(register int i=;i<=T;i++) {
printf("Case #%d:\n",i);
const int n=getint(),q=getint();
b[]=inf;
for(register int i=;i<=n;i++) {
b[i]=a[i]=getint();
}
for(register int i=;i<=q;i++) {
l[i]=getint();
r[i]=getint();
b[n+i]=x[i]=getint();
}
std::sort(&b[],&b[n+q+]);
size=std::unique(&b[],&b[n+q+])-b;
for(register int i=;i<=n;i++) {
const int id=std::lower_bound(&b[],&b[size],a[i])-b;
t.root[i]=t.modify(t.root[i-],,size-,id);
}
for(register int i=;i<=q;i++) {
const int id=std::lower_bound(&b[],&b[size],x[i])-b;
const int leq=b[t.queryleq(t.root[l[i]-],t.root[r[i]],,size-,id)];
const int geq=b[t.querygeq(t.root[l[i]-],t.root[r[i]],,size-,id)];
printf("%d\n",std::min(std::abs(x[i]-leq),std::abs(x[i]-geq)));
}
}
return ;
}

[HihoCoder1169]猜单词的更多相关文章

  1. python 游戏(猜单词Hangman)

    1.游戏思路和流程图 实现功能:随机一个单词让玩家猜测(后续难度实现修改为成语填空,成语必须要有提示,可修改猜的次数,增加连续猜成语,难度系数随着次数的增加而增加) 游戏流程图 2. 单词库和模块 i ...

  2. 关于切片/截取(slice)和random模块的使用(实例:猜单词小游戏)

    切片和random的使用在源码中都有注释(可以直接下载):https://github.com/NoobZeng/GuessWords 1. README.MD 基于Python的猜单词游戏 猜单词小 ...

  3. Python小游戏 -- 猜单词

    Python初学者小游戏:猜单词 游戏逻辑:就像我们曾经英语学习机上的小游戏一样,电脑会从事先预置的词库中抽取单词,然后给出单词的字母数量,给定猜解次数,然后让玩家进行猜测,并给出每次猜测的正确字母与 ...

  4. [LeetCode] 843. Guess the Word 猜单词

    This problem is an interactive problem new to the LeetCode platform. We are given a word list of uni ...

  5. [Swift]LeetCode843. 猜猜这个单词 | Guess the Word

    This problem is an interactive problem new to the LeetCode platform. We are given a word list of uni ...

  6. 任务驱动,学习.NET开发系列第2篇------单词统计

    一 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分人学习软件开发技术是通过看书,看视频,听老师上课的方式.这些方式有一个共同点即按知识点进行讲解.比如拿c#编程为例,首先是讲解大量的基础概念 ...

  7. python练手项目

    文本操作 逆转字符串--输入一个字符串,将其逆转并输出. 拉丁猪文字游戏--这是一个英语语言游戏.基本规则是将一个英语单词的第一个辅音音素的字母移动到词尾并且加上后缀-ay(譬如"banan ...

  8. 【C++】命令行Hangman #2015年12月15日 00:20:27

    增加了可以在构造Hangman对象时通过传入参数设定“最大猜测次数”的功能.少量修改.# 2015年12月15日 00:20:22 https://github.com/shalliestera/ha ...

  9. cryptography

    密码关还是有很多变态的题的,整理一下力所能及的吧. Circular Crypto(Asis-CTF2013) 这题只给了一张图片 仔细看一下就知道,这是几个单独的环,把它们分别整理出来.因为看着眼花 ...

随机推荐

  1. NYOJ 305 表达式求值 (字符串处理)

    题目链接 描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值是108等等.经过训练, ...

  2. (4)剑指Offer之链表相关编程题

    一 链表中倒数第k个节点 题目描述: 输入一个链表,输出该链表中倒数第k个结点 问题分析: 一句话概括: 两个指针一个指针p1先开始跑,指针p1跑到k-1个节点后,另一个节点p2开始跑,当p1跑到最后 ...

  3. linux设置时区同步时间

    linux设置时区同步时间 一.运行tzselect sudo tzselect 在这里我们选择亚洲 Asia,确认之后选择中国(China),最后选择北京(Beijing) 如图:   二.复制文件 ...

  4. 大数据系列之分布式数据库HBase-0.9.8安装及增删改查实践

    若查看HBase-1.2.4版本内容及demo代码详见 大数据系列之分布式数据库HBase-1.2.4+Zookeeper 安装及增删改查实践 1. 环境准备: 1.需要在Hadoop启动正常情况下安 ...

  5. [转载]FFmpeg完美入门[4] - FFmpeg应用实例

    1 用FFserver从文件生成流媒体 一.安装ffmpeg 在ubuntu下,运行sudo apt-get ffmpeg 安装ffmpeg,在其他linux操作系统下,见ffmpeg的编译过程(编译 ...

  6. go语言入门(三)

    条件语句 go语言的条件语句结构如下: go语言的条件语句和其他语言类似.简单列举下: 1.if 语句,布尔表达式不需要括号 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 2 ...

  7. 服务器或普通PC裸机安装 ESXI6.5

    ESXI :安装包 http://pan.baidu.com/s/1c2gM0Xq (包含注册机和其他套件,驱动打包工具) ESXI 6.5 在服务器安装比较方便,一般intel 的网卡都没多大问题, ...

  8. Qt5.4 webview 不能打开网址

    在使用Qwebview浏览器时不能打开网络地址,并报下面的错误 Starting E:\WorkSpace\QtWorkSpace\build-webTest-Desktop_Qt_5_4_2_MSV ...

  9. c++ primer 2 变量和基本类型

    2.1 基本内置类型 基本内置类型是C++“自带”的类型,区别于标准库定义的类型.使用时不需要应用标准库就可以使用,我们可以理解为数字型有下面这些 整形:就是整数或者是没有小数位的数.它包括bool( ...

  10. [实战]MVC5+EF6+MySql企业网盘实战(18)——文件上传,下载,修改

    写在前面 经过一段时间的秀秀改改,终于把文件上传下载,修改文件夹文件名称的功能实现了. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企 ...