tc674div1b
题意:给出n个孩子的初始位置,和每个孩子开始的朝向(左或者右),然后孩子的行走规则是,速度始终为1,两人相遇则两人立即转身背向而行。
现在有q次询问,每次问编号为i的孩子在时间t距离原点的距离。返回所有询问之和。
分析:我们现在用另一种方式思考这个行走模式。我们认为,当两个孩子相遇时,他们并没有背向而行,而是交换了身份,并继续保持自己的行进方向和速度。
这样以来,我们就可以认为所有人都始终保持匀速直线运动。每次询问就变成了:设询问编号为i的孩子开始所处的排名(即初始时从左往右数第几个人是他)为x,问现在排名为x的人的坐标。
这个问题可以使用二分查找来解决,用两个数组分别存储向左走的人的坐标和向右走的人的坐标。
每次二分查找这个坐标值。对于一个给定的坐标值我们分别在两个数组中找到它左边有多少人,两组在其左边的人数之和应为排名-1。
当然,在两个数组中数人数的时候有两点需要注意。一个是根据时间平移所有人的坐标。由于坐标是相对的所以不需要平移每个人,只需要反向平移我们枚举的坐标点即可。
二是在数人数的时候仍然要用到二分查找,但是可以直接调用upper_bound进行处理。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime> using namespace std; const int MOD = (int)(1e9) + ;
const int MAX_N = (int)(2e5) + ; class FindingKids {
public:
long long getSum(int, int, int, int, int);
}; long long a, b, c;
long long lkid[MAX_N];
long long rkid[MAX_N];
int lcnt, rcnt;
pair<int, int> pos[MAX_N];
int ranks[MAX_N]; void generate(int n)
{
long long p;
lcnt = rcnt = ;
set<long long> my_set;
for (int i = ; i < n; i++)
{
a = (a * b % MOD + c) % MOD;
p = a % (MOD - n + i + );
if (my_set.count(p) > )
p = MOD - n + i;
my_set.insert(p);
pos[i] = make_pair(p, i);
if (p % == )
{
rkid[rcnt++] = p;
}else
{
lkid[lcnt++] = p;
}
}
} long long work(int id, long long x)
{
long long l = min(lkid[] - x, rkid[] + x);
long long r = max(lkid[lcnt - ] - x, rkid[rcnt - ] + x);
while (l < r)
{
long long mid = l + (r - l) / ;
long long lnum = upper_bound(lkid, lkid + lcnt, mid + x) - lkid;
long long rnum = upper_bound(rkid, rkid + rcnt, mid - x) - rkid;
if (lnum + rnum < id + )
l = mid + ;
else
r = mid;
}
return abs(l);
} long long FindingKids::getSum(int n, int q, int A, int B, int C) {
a = A;
b = B;
c = C;
generate(n);
sort(pos, pos + n);
for (int i = ; i < n; i++)
{
ranks[pos[i].second] = i;
}
sort(lkid, lkid + lcnt);
sort(rkid, rkid + rcnt);
long long ret = ;
for (int i = ; i < q; i++)
{
a = (a * b % MOD + c) % MOD;
int kid = ranks[a % n];
a = (a * b % MOD + c) % MOD;
long long my_time = a;
long long temp = work(kid, my_time);
ret += temp;
}
return ret;
}
tc674div1b的更多相关文章
随机推荐
- JavaScript indexOf() 方法 和 lastIndexOf() 方法
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索. 语法: in ...
- sql server cross/outer apply 用法
这是 sql server 帮助文档关于apply的描述: 使用 APPLY 运算符(2005或以上版本)可以为实现查询操作的外部表表达式返回的每个行调用表值函数.表值函数作为右输入,外部表表达式作为 ...
- CSS基本知识1-CSS基本概念
CSS基本概念: 选择器{属性:值;属性:值} CSS继承:子元素继承父元素样式,父子关系看DOM结构. CSS覆盖: 浏览器缺省设置 外部样式表 内部样式表(位于 <head> 标签内部 ...
- 读书笔记---《火球:UML大战需求分析》
书评 作为一本UML和需求分析的入门书来说还算可以,写的比较接地气,如果是做过很多项目的读者,很容易找到共鸣点. 美中不足:部分概念可能有错误,其中对于Component和Artifact的解释明显和 ...
- C 语言学习 第五次作业总结
第五次作业,主要学习和复习的是几种循环结构的使用. 在前一次的课堂上,同学们已经学习了分支语句的使用.分支语句和循环语句配合使用,就可以写出更多的,逻辑功能丰富的代码了. 逻辑功能的丰富,也意味着学习 ...
- java 装饰者模式与继承的区别
装饰者模式目标 把许多要实现的功能,加载在子类上,类的继承,显得很臃肿,装饰着模式是在不改变原有类文件和使用继承的情况下,通过创建一个包装对象动态地扩展一个对象的功能,相比生成子类更为灵活 装饰者模式 ...
- 关于dll
今日看到一个不带dllmain的dll,忽然觉得有点奇怪,然后查了一下,原来dll还可以不需要dllmain,甚至可以自己定义入口 先mark以下的资料,有空再总结一下...同时dll劫持,有必要亲身 ...
- 【转】单调队列优化DP
转自 : http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列是一种严格单调的队列,可以单调递增,也可以单调递减.队 ...
- Android网络文件下载模块整理
一.知识基础 tomcat服务器配置 理解http协议 理解javaIO操作相关知识 SDcard操作知识 Android 权限配置 二.实现步骤 1.从网上获取资源 public String do ...
- jquery 离开页面提示信息
<script> $(window).bind('beforeunload', function () { return '您输入的内容尚未保存,确定离开此页面吗?'; });</s ...