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提出的事件流,即事件由页面元素 ...
随机推荐
- 为什么要用Go语言做后端
FMZ数字货币量化平台 www.fmz.com, 后端使用Go语言,这里是创始人Zero谈论使用Go语言所带了的便利.原帖地址:https://www.zhihu.com/question/27172 ...
- spring cloud config搭建说明例子(四)-补充配置文件
服务端 ConfigServer pom.xml <dependency> <groupId>org.springframework.cloud</groupId> ...
- [ZJOI2008]杀蚂蚁
题意翻译 注意在(0,0)已经有蚂蚁的时候是不会生成新蚂蚁的 还有如果有蚂蚁扛着蛋糕,但是不在某个炮的范围内,炮仍然会打最近的蚂蚁 题目描述 最近,佳佳迷上了一款好玩的小游戏:antbuster. 游 ...
- Codeforces 1131 (div 2)
链接:http://codeforces.com/contest/1131 A Sea Battle 利用良心出题人给出的图,不难看出答案为\(2*(h1+h2)+2*max(w1,w2)+4\)由于 ...
- 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids
题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...
- MySQL与Sqlserver数据获取
由于项目要求,一个.net mvc登录注册的东西网站必须放弃sqlserver数据去使用MySQL数据库,因此我遇到了一些问题,并找出相应的解决方法, 因为sqlserver跟MySQL的数据引擎不同 ...
- 上传一个npm包
1.先创建一个npm账号 https://www.npmjs.com/signup 2.在cmd里输入命令进入项目文件夹 3.使用npm init 命令创建一个package.json(确保nodej ...
- 微信服务号获取openId流程(订阅号)
微信公众平台官网:https://mp.weixin.qq.com/ 微信测试开发平台官网:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandb ...
- SQlite数据库框架:LitePal
常用的数据库框架Android的发展的速度是难以置信的,Android出来哪一年我还在小学上学很,还能很清楚的记得,那年一切,但是那个时候的我怎么可能也不会想到自己将来会要去做Android.Andr ...
- C++_运算符重载 总结
什么是运算符的重载? 运算符与类结合,产生新的含义. 为什么要引入运算符重载? 作用:为了实现类的多态性(多态是指一个函数名有多种含义) 怎么实现运算符的重载? 方式:类的成员函数 或 友元函数(类外 ...