http://acm.hdu.edu.cn/showproblem.php?pid=3303

Harmony Forever

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 813    Accepted Submission(s): 222

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.
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.
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 2
0
Sample Output
Case 1:
1
2
1

Case 2:
1
Source

题解:

很显然的线段树问题,但是这个题有点技巧就是利用抽屉原理来降低复杂度。

什么是抽屉原理?抽屉原理也叫鸽巢原理,鸽巢原理就是给定N+1个数,则必定至少有两个数Mod(N)的余数是相同的! 假设要求的MOD是Y,则首先查找[0,Y-1]区间的最小值,因为这样的区间不会有两个数的余数相同,记录下结果。然后依次查找[Y,Y+Y-1],[Y+Y,Y+Y+Y-1]。。。。等区间,每个区间都会找出一个最小值,将这些最小值对Y进行取模,得到最小值!

这题还要注意:范围较小的时候直接查找,否则TLE。

代码:

 #include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector> using namespace std;
#define N 500000
#define INF 100000000
vector<int> vct; struct Nod
{
int l,r,mins;
}node[(N<<)+]; int maxInput;
int posArray[N+]; void building(int l,int r,int p)
{
node[p].l = l;
node[p].r = r;
node[p].mins = INF;
if(l==r) return ;
int mid = (l+r)>>;
building(l,mid,p<<);
building(mid+,r,p<<|);
} void update(int x,int p)
{
if(node[p].l>x||node[p].r<x) return;
if(node[p].l == node[p].r&&node[p].l==x)
{
node[p].mins = x;
return;
}
update(x,p<<);
update(x,p<<|);
node[p].mins = min(node[p<<].mins,node[p<<|].mins);
}
/**RE的查询方式 int query(int l,int r,int p) //找[l,r]区间的最小值
{
if(node[p].l == l && node[p].r == r) return node[p].mins;
int mid = (node[p].l+node[p].r)>>1;
if(r<=mid) return query(l,r,p<<1);
else if(mid>l) return query(l,r,p<<1|1);
else return min(query(l,mid,p<<1),query(mid+1,r,p<<1|1));
} */
int Query(int l,int r,int index)//找[l,r]区间的最小值
{
if(node[index].l>r || node[index].r<l) return INF;
if(node[index].l>=l && node[index].r<=r) return node[index].mins;
if(node[index].l < node[index].r)
return min(Query(l,r,index<<),Query(l,r,index<<|));
return INF;
} int search(int y)
{
int minAns = INF,id = ,i;
for(i=vct.size()-;i>=;i--)
{
if(vct[i]%y== ) return i+;
if(vct[i]%y<minAns)
{
minAns = vct[i]%y;
id = i+;
}
}
return id;
} int solve(int y) //抽屉原理
{
int l=,r=y-,minAns=INF,id,temp;
while(l<=maxInput)
{
if(maxInput<r) r=N;
temp = Query(l,r,);
if(temp!=INF)
{
if(temp%y<minAns)
{
minAns = temp%y;
id = posArray[temp];
}
else if(temp%y == minAns && posArray[temp] > id)
{
id = posArray[temp];
}
}
l+=y;
r+=y;
}
return id;
} int main()
{
int t,cas=;
while(~scanf("%d",&t)&&t)
{
building(,N,);
char op[];
maxInput = ;
vct.clear();
if(cas!=) printf("\n");
printf("Case %d:\n",cas++);
while(t--)
{
scanf("%s",op);
if(op[]=='B')
{
int x;
scanf("%d",&x);
if(maxInput<x) maxInput = x;
vct.push_back(x);
posArray[x] = vct.size();
update(x,);
}
else if(op[]=='A')
{
int y;
scanf("%d",&y);
if(vct.size()==) puts("-1");
else if(y<=) printf("%d\n",search(y)); //防超时
else printf("%d\n",solve(y));
}
}
}
return ;
}

hdu 3303 Harmony Forever (线段树 + 抽屉原理)的更多相关文章

  1. HDU 3303 Harmony Forever 前缀和+树状数组||线段树

    Problem Description We believe that every inhabitant of this universe eventually will find a way to ...

  2. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  3. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  4. 浅谈可持久化Trie与线段树的原理以及实现(带图)

    浅谈可持久化Trie与线段树的原理以及实现 引言 当我们需要保存一个数据结构不同时间的每个版本,最朴素的方法就是每个时间都创建一个独立的数据结构,单独储存. 但是这种方法不仅每次复制新的数据结构需要时 ...

  5. HDU 5091---Beam Cannon(线段树+扫描线)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5091 Problem Description Recently, the γ galaxies bro ...

  6. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  7. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  8. HDU 5820 (可持久化线段树)

    Problem Lights (HDU 5820) 题目大意 在一个大小为50000*50000的矩形中,有n个路灯.(n<=500000) 询问是否每一对路灯之间存在一条道路,使得长度为|x1 ...

  9. HDU 5861 Road (线段树)

    Road 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Description There are n villages alo ...

随机推荐

  1. Linux进程IPC

    IPC mechanisms supported by Linux include pipes, named pipes, semaphores, message queues, shared mem ...

  2. compile ffmpeg

    download SDL 1.2.xxx version source code. 1) configure 2) make & make instll download recent ffm ...

  3. 会话状态Session解析以及原理分析

    我们知道web网站在客户端存储数据有三种形式:1. Cookie   2. hidden(隐藏域) 3.QueryString 其中viewstate什么的都是通过第二种方式隐藏域存储滴. 客户端存储 ...

  4. javascript开发中的封装模式(转)

    var bgAuido={ audio : pingfan.$$('audio'), audioBtn : pingfan.$$('audioBtn'), init : function(){ var ...

  5. 关于Git的分支

    分支是代码管理的利器.如果没有有效的分支管理.代码管理就适应不了复杂的开发过程和 项目的需要. 分支命令概述: 在Git中分支管理使用命令git branch.该命令的主要用法如下: 用法一: git ...

  6. 基于Selenium2+Java的UI自动化(4) - WebDriver API简单介绍

    1. 启动浏览器 前边有详细介绍启动三种浏览器的方式(IE.Chrome.Firefox): private WebDriver driver = null; private String chrom ...

  7. copy与deepcopy

    对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 对于字典.元祖.列表 而言,进行赋值.浅拷贝和深拷贝时,其内存地址的变化是不同的. 赋值,只是创建一个变量,该 ...

  8. 让progressDialog不会触摸消失

    项目中的进度菊花圈,在网络请求的时候会出现,但是手一触碰到屏幕,就会消失,看了下自己的设置,给对话框设置了该方法: progressDialog.setCancelable(true); 点击Prog ...

  9. 在shell的if条件里,判断 a>0 且 (b>0 或 c>0) ,如何编写?

    if [ $b -gt 0 -o $c -gt 0 -a $a -gt 0 ]; then.fi对shell中的关系运算符说明如下:-gt 表示greater than,大于-lt 表示less th ...

  10. ###Canny边缘检测算子

    开源中国. #@date: 2014-06-20 #@author: gerui #@email: forgerui@gmail.com 一.一阶微分边缘算子 1. 一阶微分边缘检测算子也称梯度边缘算 ...