poj3145 / hdu3303 Harmony Forever(树状数组 + 鸽巢原理)
来源:互联网 发布:大学生网贷数据分析 编辑:程序博客网 时间:2024/06/11 22:01
Harmony Forever
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1633 Accepted Submission(s): 474
Problem Description
We believe that every inhabitant of this universe eventually will find a way to live together in harmony and peace; that trust, patience, kindness and loyalty will exist between every living being of this earth; people will find a way to appreciate and cooperate with each other instead of continuous bickering, arguing and fighting. Harmony -- the stage of society so many people dream of and yet it seems so far away from now ...
Fortunately, the method of unlocking the key to true Harmony is just discovered by a group of philosophers. It is recorded on a strange meteorite which has just hit the earth. You need to decipher the true meaning behind those seemingly random symbols ... More precisely, you are to write a program which will support the following two kinds of operation on an initially empty set S :
1.
B X : Add number X to set S . The Kth command in the form of B X always happens at time K , and number X does not belong to set S before this operation.
2.
A Y : Of all the numbers in set S currently, find the one which has the minimum remainder when divided by Y . In case a tie occurs, you should choose the one which appeared latest in the input. Report the time when this element is inserted.
It is said that if the answer can be given in the minimum possible time, true Harmony can be achieved by human races. You task is to write a program to help us.
Fortunately, the method of unlocking the key to true Harmony is just discovered by a group of philosophers. It is recorded on a strange meteorite which has just hit the earth. You need to decipher the true meaning behind those seemingly random symbols ... More precisely, you are to write a program which will support the following two kinds of operation on an initially empty set S :
1.
B X : Add number X to set S . The Kth command in the form of B X always happens at time K , and number X does not belong to set S before this operation.
2.
A Y : Of all the numbers in set S currently, find the one which has the minimum remainder when divided by Y . In case a tie occurs, you should choose the one which appeared latest in the input. Report the time when this element is inserted.
It is said that if the answer can be given in the minimum possible time, true Harmony can be achieved by human races. You task is to write a program to help us.
Input
There are multiple test cases in the input file. Each test case starts with one integer T where 1<=T<=40000 . The following T lines each describe an operation, either in the form of ``B X " or ``A Y " where 1<=X , Y<=500000 .
T = 0 indicates the end of input file and should not be processed by your program.
T = 0 indicates the end of input file and should not be processed by your program.
Output
Print the result of each test case in the format as indicated in the sample output. For every line in the form of ``A Y ", you should output one number, the requested number, on a new line; output -1 if no such number can be found. Separate the results of two successive inputs with one single blank line.
Sample Input
5 B 1 A 5 B 10 A 5 A 40 2 B 1 A 20
Sample Output
Case 1: 1 2 1 Case 2:1
题意:
对一个集合S进行如下操作:1.B x 添加一个元素x到集合S中, 发生时间为原集合的元素总数加一, 并且保证此次操作之前,集合S中都不存在x2.A y 在集合S的所有数中,对y进行取余操作,输出其中最小的,若存在相同的,则输出发生最近操作的数,空集则输出 -1;当然题目都是求插入元素的时间。思路:
容易想到的方法是暴力:开一个数组为x[i]大小的q数组,对于每次插入操作,更新数组的每一个值,那么询问的时候,只需要输出q[y[i]]就可以了。但是这题由于 1 <= x, y <= 500000, 时间上(T(O) = N ^ 2)肯定不允许。于是想到利用鸽巢原理来进行分段:对每个y,由鸽巢原理,y + 1个数中,必定存在mod y存在相同的数,那么分为n个区间段进行更新和查询即可,即[0, y - 1], [y, 2 * y - 1]...[k * y, max(y)], 我们只需要这些段取模以后的最小值。对于区间的最小值, 可以用树状数组或者线段树维护,T(O) = O(lgmax(x[i])),但是很明显如果x[i]很小是,时间复杂度就会变成O(N), 此时可以直接用暴力:对于每次询问, 如果x[i] < lim, 直接可以输出数组q, 大于的时候, 则进行分段查找,每次插入更新两个数组q和c即可,于是我们开一个长度max(x[i])的数组c,没插入一个数, 就在数组c中标记已插入。反思:
自己对线段树理解还算可以,但是不太擅长树状数组,所以这次选择用树状数组,但由于更新c[i]数组的Add()函数时候 一个细节错了,找了好几天,真是无语了。自己代码优化不是很好。AC代码:
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<algorithm>using namespace std;const int lim = 1000;const int maxn = 5e5 + 10; // 在线做法把数组开到最大, 时间就卡死了!int q[maxn + 5], c[maxn + 5], a[maxn + 5], time[maxn + 5];int t;inline int lowbit(int x){ return x & (-x);}void Add(int x){ while(x <= maxn) { c[x]++; x += lowbit(x); }}// 插入操作void Insert(int x){ time[++t] = x; a[x] = t; for(int i = 1; i <= lim; i ++) { if(q[i] == 0) q[i] = t; else if(x % i <= time[q[i]] % i) q[i] = t; } Add(x);}// 树状数组求前n项和int Sum(int x){ int sum = 0; while(x > 0) { sum += c[x]; x -= lowbit(x); } return sum;}// 查找每段的最小值int Binary(int be, int en){ int l, r; if(be == 0) l = 1; else l = be; if(en > maxn) r = maxn; else r = en; int pre = Sum(l - 1); int askmin = -1; // 二分查找 while(l <= r) { int mid = (l + r) >> 1; int now = Sum(mid); if(now > pre) { r = mid - 1; askmin = mid;// 找到一个值才更新,改动左端点不更新 } else l = mid + 1; } return askmin;}void enquiry(int x){ // 空集输出'-1' if(t == 0) puts("-1"); //小的询问直接输出 else if (x <= lim) printf("%d\n", q[x]); else { int cur = x - 1; // 分段 int l = 0, r = x - 1; while(l <= maxn) { int k = Binary(l, r); if(k > 0 && ((k % x < cur % x) || ((k % x == cur % x) && (a[k] > a[cur])))) cur = k; l += x, r += x; } printf("%d\n", a[cur]); }}int main(){ int Case = 1; int T; while(scanf("%d", &T), T) { t = 0; if(Case != 1) puts(""); printf("Case %d:\n", Case++); // 清除冗余数据 for(int i = 0; i <= maxn; i ++) { q[i] = 0; time[i] = 0; c[i] = 0; a[i] = 0; } char command[2]; int x; while(T--) { scanf("%s%d",command, &x); if(command[0] == 'B') Insert(x); else enquiry(x); } } return 0;}
0 0
- poj3145 / hdu3303 Harmony Forever(树状数组 + 鸽巢原理)
- POJ3145: Harmony Forever
- POJ 3145 HDU 3303 Harmony Forever 线段树 + 鸽巢定理
- hdu 3303 Harmony Forever
- POJ 3145 Harmony Forever
- D POJ 3145 Harmony Forever
- hdu Harmony Forever (线段树 )
- POJ 3145 Harmony Forever 笔记
- poj 3145 Harmony Forever(线段树)
- HDU 3303 Harmony Forever(数学)
- poj 3145 Harmony Forever
- POJ-3145-Harmony Forever-线段树暴力
- 树状数组 原理
- 树状数组原理解析
- 树状数组原理(转载)
- 树状数组---原理代码实现
- 树状数组(模板+原理)
- 树状数组原理及模板
- 知乎上关于机器人的热门有趣的问答分享与机器人探索之路的点点滴滴
- 程序软件版本管理
- 备份基础与命令
- 三 数 最 大 值 : 输 入 3 个 整 数 , 输 出 其 中 的 最 大 值 。
- U深度-重装电脑系统
- poj3145 / hdu3303 Harmony Forever(树状数组 + 鸽巢原理)
- java rotate 90_2
- 如何获得想要的浮点数长度(如Float类型的数据)
- 效率为王!11款最高效的团队协作工具
- MySQL基础之索引理论篇
- android安装
- JavaWeb:将欢迎界面转发到servlet
- MySQL基础之索引实战篇
- WIN2008SERVER下SQL 2000的问题