分析:一个最暴力的想法是把加入到集合S的数据一个个按顺序保存起来,然后每次查询的时候由后向前计算余数,如果遇到余数为0的,就直接把时间输出,否则就一直比较到最后找余数最小时间最晚的,这样查询的时间复杂度是n(当前S的元素个数)。

另一个想法就是利用x、y的数据范围,建线段树表示[1,500000]这个区间,用来更新和查询任意[a,b]区间的最小值。因为[m*y,(m + 1)y - 1]内每个数除y的余数都是唯一的,而且被除数越小余数就越小,所以我们可以查询每个小区间的最小值,再比较应该取哪个时间就可以了。查询的时间复杂度为(maxN/y)*lg(maxN),可见y越大查询时间越短。但y很小时,就要进行很多次对线段树的查询才能得出结果,所以当y很小时,应该用暴力的方法查询。

 #pragma warning(disable:4996)
#include <cstdio>
#include <set>
#include <stack>
#include <vector>
#include <algorithm>
#include <map>
#define maxN 1000001
using namespace std;
int sum[maxN << ], data[maxN];
int stk[maxN], s;
//向上更新,rt是要更新的节点的下标
void pushUp(int rt){
int m = rt << ;
if (sum[m] != -){
sum[rt] = sum[m];
}
else{
sum[rt] = sum[m | ];
}
}
//初始化线段树
void initTree(int a, int b, int rt){
sum[rt] = -;
if (a == b){
return;
}
int m = rt << ;
initTree(a, (a + b) / , m);
initTree((a + b) / + , b, m | );
}
//更新节点
void update(int tgt, int time, int a, int b, int rt){
if (a == b){
sum[rt] = a;
data[a] = time;
return;
}
int m = rt << ;
if (tgt > (a + b) / ){//更新右子树
update(tgt, time, (a + b) / + , b, m | );
}
else{//更新左子树
update(tgt, time, a, (a + b) / , m);
}
pushUp(rt);
}
int query(int ta, int tb, int a, int b, int rt){
if (ta <= a && tb >= b || sum[rt] == -){
return sum[rt];
}
int ret = -, m = rt << ;
if (ta <= (a + b) / ){//查询左子树
ret = query(ta, tb, a, (a + b) / , m);
}
if (ret == - && tb > (a + b) / ){//查询右子树
ret = query(ta, tb, (a + b) / + , b, m | );
}
return ret;
}
int query(int x){
int ret = 0xfffffff, start = , end = x - ,rmdRet = x;
do{
int temp = query(start, end, , , );
int rmdTemp = temp % x;
if (temp != -){
if(rmdRet > rmdTemp){
rmdRet = rmdTemp;
ret = temp;
}
else if (rmdRet == rmdTemp && data[ret] < data[temp]){
ret = temp;
}
}
start = end + ;
end += x;
}while (end < );
if (ret == 0xfffffff){
return -;
}
else{
return data[ret];
}
}
int main(){
int t, x, time;
char op;
int caseNum = ;
while (scanf("%d", &t), t){
if (caseNum != ){
printf("\n");
}
printf("Case %d:\n", caseNum++);
initTree(, , );
s = ;
time = ;
for (int i = ; i <= t; i++){
scanf("%*c%c%d", &op, &x);
if (op == 'B'){
update(x, time++, , , );
stk[s++] = x;
}
else{
if (x > ){
printf("%d\n", query(x));
}
else{
int rmd = x,ans = -;
bool flag = false;
for (int i = s - ; i >= ; i--){
if (stk[i] % x == ){
printf("%d\n", i + );
flag = true;
break;
}
else if(stk[i] % x < rmd){
rmd = stk[i] % x;
ans = i + ;
}
}
if (!flag){
printf("%d\n", ans);
}
}
}
}
}
return ;
}

hdu3303的更多相关文章

  1. JS里关于事件的常被考察的知识点:事件流、事件广播、原生JS实现事件代理

    1.JS里面的事件流 DOM2级事件模型中规定了事件流的三个阶段:捕获阶段.目标阶段.冒泡阶段,低版本IE(IE8及以下版本)不支持捕获阶段 捕获事件流:Netscape提出的事件流,即事件由页面元素 ...

随机推荐

  1. Git管理多个远程分支

    在此目录下使用GIT要注意一下几点: 因为这个目录是管理远程多个不同的分支的项目,所以使用GIT之前确认一下几点: 打开git bash,使用命令:git config –list查看目前本地的目录文 ...

  2. Matlab vs Python 作图

    -- Matlab 作图示例 x=-3:0.00003:3; y1=sin(x)./x; y2=x./sin(x); plot(x,y1,x,y2); -- Python 作图示例 import nu ...

  3. 全面学习ORACLE Scheduler特性(4)创建和管理Schedule

    三.使用Schedules 10g 中新推出的SCHEDULER可能确实会让很多初接触的朋友感觉晕头晕脑,相比之前的jobs,SCHEDULER中新增的概念太多.比如说jobs,仍然可以理解成之前版本 ...

  4. Spring Boot (32) Lock 本地锁

    平时开发中,有时会双击提交表单造成重复提交,或者网速比较慢时还没有响应又点击了按钮,我们在开发中必须防止重复提交 一般在前台进行处理,定义个变量,发送请求前判断变量值为true,然后把变量设置为fal ...

  5. MacOS 下安装 MySQL8.0 登陆 MySQL

    按照 官方教程 ,下载安装包,点击安装后,如需在命令行启动,还需设置命令路径: 在命令行中,打开配置文件 .bash_profile: vim ~/.bash_profile 在最后一行加上: PAT ...

  6. V形

    <!doctype html><html><head><meta charset="utf-8"><title>无标题文 ...

  7. Fiddler——基本常识

    web session界面 inspector面板 xml:查看XML数据 json:查看json数据 raw:可以完整查看请求的内容 cookies:可以查看请求的cookie header:查看请 ...

  8. jsp学习笔记 - 内置对象 application

    ---恢复内容开始--- 1.application一般用this.getServletContext()替代 2.appllication有一个非常有用的函数 getRealPath(),获取绝对路 ...

  9. treetable adding nodes at root level

    describe("loadBranch()", function() {     beforeEach(function() {     this.newRows = " ...

  10. linux ssh 利用scp传输文件

    使用方式如下: 1.上传本地文件到服务器 scp /path/filename username@servername:/path/ 例如scp /var/www/test.php root@192. ...