[HihoCoder1169]猜单词
题目大意:
给你一个数列,问区间[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]猜单词的更多相关文章
- python 游戏(猜单词Hangman)
1.游戏思路和流程图 实现功能:随机一个单词让玩家猜测(后续难度实现修改为成语填空,成语必须要有提示,可修改猜的次数,增加连续猜成语,难度系数随着次数的增加而增加) 游戏流程图 2. 单词库和模块 i ...
- 关于切片/截取(slice)和random模块的使用(实例:猜单词小游戏)
切片和random的使用在源码中都有注释(可以直接下载):https://github.com/NoobZeng/GuessWords 1. README.MD 基于Python的猜单词游戏 猜单词小 ...
- Python小游戏 -- 猜单词
Python初学者小游戏:猜单词 游戏逻辑:就像我们曾经英语学习机上的小游戏一样,电脑会从事先预置的词库中抽取单词,然后给出单词的字母数量,给定猜解次数,然后让玩家进行猜测,并给出每次猜测的正确字母与 ...
- [LeetCode] 843. Guess the Word 猜单词
This problem is an interactive problem new to the LeetCode platform. We are given a word list of uni ...
- [Swift]LeetCode843. 猜猜这个单词 | Guess the Word
This problem is an interactive problem new to the LeetCode platform. We are given a word list of uni ...
- 任务驱动,学习.NET开发系列第2篇------单词统计
一 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分人学习软件开发技术是通过看书,看视频,听老师上课的方式.这些方式有一个共同点即按知识点进行讲解.比如拿c#编程为例,首先是讲解大量的基础概念 ...
- python练手项目
文本操作 逆转字符串--输入一个字符串,将其逆转并输出. 拉丁猪文字游戏--这是一个英语语言游戏.基本规则是将一个英语单词的第一个辅音音素的字母移动到词尾并且加上后缀-ay(譬如"banan ...
- 【C++】命令行Hangman #2015年12月15日 00:20:27
增加了可以在构造Hangman对象时通过传入参数设定“最大猜测次数”的功能.少量修改.# 2015年12月15日 00:20:22 https://github.com/shalliestera/ha ...
- cryptography
密码关还是有很多变态的题的,整理一下力所能及的吧. Circular Crypto(Asis-CTF2013) 这题只给了一张图片 仔细看一下就知道,这是几个单独的环,把它们分别整理出来.因为看着眼花 ...
随机推荐
- input复选框checkbox默认样式纯css修改
修改之前的样式 修改之后的样式 html <input type="checkbox" name="btn" id="btn1"&g ...
- jsoup抓取网页报错UnsupportedMimeTypeException
今天在用Jsoup爬虫的时候两次遇到下面错误 Exception in thread "main" org.jsoup.UnsupportedMimeTypeException: ...
- struts入门
1.概念
- linux下生成core dump文件方法及设置【转】
转自:http://blog.csdn.net/mrjy1475726263/article/details/44116289 源自:http://andyniu.iteye.com/blog/196 ...
- VS2015_动态链接库学习
非MFC动态链接库 创建一个名为ex1的Win32项目 创建一个DLL项目,保留预编译的头文件 默认文件 创建完成项目之后,包含几个默认的文件 stdafx.h文件用于包含标准系统包含的头文件 ...
- 监控MYSQL主从同步配置中监控从库运行状态的脚本
代码如下: #!/bin/bash #Check MySQL Slave's Runnning Status #Crontab time 00:10 MYSQLPORT=`netstat -na|gr ...
- UBuntu14.04 --vim安装YouCompleteMe插件
说明 我电脑的系统参数(用 uname -a命令查看)如下: Linux avyn-Lenovo --generic #-Ubuntu SMP Tue Mar :: UTC i686 i686 i68 ...
- java基础2 判断语句:if ... else 语句和 switch 语句
一.if ... else 判断语句 1.if ... else 判断语句的格式 1.1.格式一 if(判断条件){ 执行不满足条件的语句 } 1.2.格式二 if(判断语句){ 满足条件的语句 }e ...
- 构建基于TCP的应用层通信模型
各层的关系如下图,表述的是两个应用或CS间通信的过程: 通常使用TCP构建应用时,需要考虑传输层的通信协议,以便应用层能够正确识别消息请求.比如,一个请求的内容很长(如传文件),那肯定要分多次发送 ...
- Linux文档时间戳查看和修改——stat
查看文件时间戳命令:stat awk.txtFile: `awk.txt'Size: 20 Blocks: 8 IO Block: 4096 regular fileDevice: 801h/2 ...