hdu3303
分析:一个最暴力的想法是把加入到集合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的更多相关文章
- JS里关于事件的常被考察的知识点:事件流、事件广播、原生JS实现事件代理
1.JS里面的事件流 DOM2级事件模型中规定了事件流的三个阶段:捕获阶段.目标阶段.冒泡阶段,低版本IE(IE8及以下版本)不支持捕获阶段 捕获事件流:Netscape提出的事件流,即事件由页面元素 ...
随机推荐
- 源码阅读之LinkedList(JDK8)
inkedList概述 LinkedList是List和Deque接口的双向链表的实现.实现了所有可选列表操作,并允许包括null值. LinkedList既然是通过双向链表去实现的,那么它可以被当作 ...
- 状态压缩+枚举 UVA 11464 Even Parity
题目传送门 /* 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 状态压缩+枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 ...
- ACM_物品分堆(01背包)
物品分堆 Time Limit: 2000/1000ms (Java/Others) Problem Description: 有n个物品,物品i的重量为Wi,现在想要把这个n个物品分类两堆,求最小的 ...
- 数据传递-------@RequestParam
package com.wh.handler; /** * @RequestParam是传递参数的. * @RequestParam用于将请求参数区数据映射到功能处理方法的参数上. * * publi ...
- RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)
在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者.在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息.例如,我们希望只将error级别的错误存储到硬盘中,同时可以将 ...
- 微信小程序组件解读和分析:五、text文本
text文本组件说明: text 文本就是微信小程序中显示出来的文本. text文本组件的示例代码运行效果如下: 下面是WXML代码: [XML] 纯文本查看 复制代码 ? 1 2 3 4 <v ...
- acm练习-day1
描述现在,有一行括号序列,请你检查这行括号是否配对.输入第一行输入一个数N(0<N<=100),表示有N组测试数据.后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于1 ...
- 北大ACM(POJ1016-Numbers That Count)
Question:http://poj.org/problem?id=1016 问题点:水题. Memory: 232K Time: 125MS Language: C++ Result: Accep ...
- JAVA 学习笔记 - 基础语法1
1. 类的定义 public class 与 class的区别 一个java文件只有一个public class, 而且类名必须与文件名一致. 一个java文件可以有多个class定义,javac ...
- C++ 泛型程序设计与STL模板库(1)---泛型程序设计简介及STL简介与结构
泛型程序设计的基本概念 编写不依赖于具体数据类型的程序 将算法从特定的数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 术语:概念 用来界定具备一定功能的数据类型.例如: 将 ...