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. 利用QT开发一个记事本

    区别于之前创建爱的各个工程,这次我们在这里选择基类为QMainWindow. 然后默认目录就是 直接到对应文件中进行代码的书写: main.cpp: #include "mainwindow ...

  2. SQL Server用存储过程新建视图

    CREATE PROCEDURE [dbo].[p_GetV_view]ASBEGIN DECLARE @sqlstr1 varchar(255) DECLARE @sqlstr2 varchar(2 ...

  3. Spring Boot 获取ApplicationContext

    package com.demo; import org.springframework.beans.BeansException; import org.springframework.contex ...

  4. Greedy

    在现实世界中,有这样一类问题:它有n个输入,而它的解就由这n个输入的某个子集组成,不过这个子集必须满足某些事先给定的条件.把那些必须满足的条件称为约束条件:而把满足约束条件的子集称为该问题的可行解.问 ...

  5. Linux 的使用基础---Shell程序设计

    Shell是Linux系统中的一个重要的层次,它是用户与系统交互作用的界面.Shell除了作为命令解释程序以外,还是一种高级程序设计语言.利用Shell程序设计语言可以编写出功能很强.但代码简单的程序 ...

  6. 【转】MySQL数据库主从同步管理

    MYSQL主从同步架构是目前使用最多的数据库架构之一,尤其是负载比较大的网站,因此对于主从同步的管理也就显得非常重要,新手往往在出现主从同步错误的时候不知道如何入手,这篇文章就是根据自己的经验来详细叙 ...

  7. lex/flex 笔记

    Lex的匹配策略: 1. 按最长匹配原则确定被选中的单词 2. 如果一个字符串能被若干正规式匹配,则先匹配排在前面的正规式. lex源程序的写法:Lex源程序必须按照Lex语言的规范来写,其核心是一组 ...

  8. [转载]删除所有的.svn文件夹

    Windows 下,在DOS窗口中运行如下命令 dos 代码 for /r <你项目的路径> %i in (.svn) do rd /s /q %i Linux 下,可以先运行 显示出当前 ...

  9. [CSS][转载]内层div的margin-top影响外层div

    参考 内层div的margin-top影响外层div——引出外边距合并 div嵌套导致子区域margin-top失效不起作用的解决方法 我使用的是在外层的div中添加 border: 1px soli ...

  10. java反射温习一下

    public class LoveReflect { public static class Demo implements Serializable{ } public static void ma ...