题意:给出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的更多相关文章

随机推荐

  1. 关于javascript中this的那点事

    this可谓是JavaScript中的开发神器,使用得当的话不仅有事半功倍的效果,而且代码的逼格也更高.但是既然是神器,如果你没有足够的功力的话,那么就不要使用它,否则就有可能自毁身亡.曾几何时,我偶 ...

  2. ionic蓝牙用法

    插件cordova官网cordova-plugin-ble-central 1.开启本机蓝牙 ble.enable( function() { console.log("Bluetooth ...

  3. PRINCE2第二个原则

    PRINCE2要求项目团队吸取以前的经验教训,在项目生命周期中发现.记录和应对.吸取经验教训,应该记录在整个生命周期中,项目准备期应该回顾以往类似项目,看看是否有经验教训可以应用,如果项目是第一次做, ...

  4. Prince2七大原则(4)

    我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 第四个原则:按阶段管理. 阶段管理其实是给高层提供了项目生命周期中相对应的控 ...

  5. 通过CAGradientLayer制作渐变色效果(转)

    转载自:http://blog.it985.com/7986.html 看了极客学院的视频之后写的一篇博客,觉得不错,还是作为笔记使用. 简单介绍一下CAGradientLayer吧. Gradien ...

  6. BZOJ 1503: [NOI2004]郁闷的出纳员

    1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 10526  Solved: 3685[Submit][Stat ...

  7. COGS461. [网络流24题] 餐巾

    [问题描述] 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,…,N).餐厅可以从三种途径获得餐巾. (1)购买新的餐巾,每块需p分: (2)把用过的餐巾送到快洗部,洗一块需m天,费用需f分 ...

  8. 树莓派2安装使用小米WIfi(360 小度 腾讯wifi)

    更新2015年11月16日,jessie内核版本号4.1.13(uname -a 可以查看)直接可以驱动MT7601U,无需手动编译. 截止2015-4-6,本文基于树莓派2,raspbian,内核版 ...

  9. php常用数组函数小结

    count函数 作用:计算数组中元素的个数或对象的属性个数 返回值: 数组或者对象, 返回数组的单元个数或者对象的属性个数 Null,返回0 非数组,也非NULL,通通返回1 <?php $ar ...

  10. BerkeleyDB库简介

    BerkeleyDB库简介 BerkeleyDB(简称为BDB)是一种以key-value为结构的嵌入式数据库引擎: 嵌入式:bdb提供了一系列应用程序接口(API),调用这些接口很简单,应用程序和b ...