[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) 这题只给了一张图片 仔细看一下就知道,这是几个单独的环,把它们分别整理出来.因为看着眼花 ...
随机推荐
- 【译】第四篇 SQL Server代理配置数据库邮件
本篇文章是SQL Server代理系列的第四篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.SQL Serve ...
- Hive ORC表的使用
创建普通临时表: create table if not exists test_orc_tmp( name string, gender string, cnt BIGINT )row ...
- Deep Learning基础--word2vec 中的数学原理详解
word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了很多人的关注.由于 word2vec 的作者 Tomas Miko ...
- SPOJ DQUERY D-query (在线主席树/ 离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. SPOJ DQUERY 题意: 给出一串数,询问[L,R]区间中有多少个不同的数 . 解法: 关键是查询到某个右端点时,使其左边出现过的数都记录在 ...
- Java Eclipse 配置
1.清除多余记录 最近用eclipse打包jar的时候,需要指定一个main函数.需要先运行一下main函数,eclipse的Runnable JAR File Specification 下的Lau ...
- 工作当中遇到的ssh错误
[root@1bcc1d3f9666 externalscripts]# /usr/sbin/sshd Could not load host key: /etc/ssh/ssh_host_rsa_k ...
- set -o vi AIX下shell
set -o vi 再用esc+K键就可以使用上一条指令了 esc+kesc+j上下翻 ksh默认是emacs风格的.set -o emacs 在AIX下使用自己已经使用过的命令 在AIX下使用,默认 ...
- Linux下突然不识别无线网卡
昨天还能用wifi的Linux,今天进去后发现没有了wifi的图标,ifconfig也不显示无线网卡.怎么办? 出现这种情况,肯定是上次关机之前做了一些操作导致的.我遇到过的一个情况是:Fedora2 ...
- JavaWeb知识回顾-使用IDEA开发一个servlet.
刚刚开始学习使用IDEA进行开发,好多都不会,本来想直接导入一个eclipse项目,但是出现了好多错误,一时不知道怎么修改,所以就从最基本的servlet开始着手,慢慢熟悉这个工具,下面是使用IDEA ...
- int类中的方法(二)
25.__pos__(self,*args,**kwargs) def __pos__(self, *args, **kwargs): # real signature unknown &qu ...