FJUT3701 这也是一道数论题(线段树)题解
Problem Description
好久没出数据结构题,现在赶紧来做道数据结构题热热身
小q现在要去银行,他有个很厉害的bug能看到前面排队的人。假如当前有人正在办理业务,那么肯定要等待前一个人完成。现在有m个事件,分为3种。第一种是第x时刻有客人到银行办理业务,用时t。第二种是第i个事件中的客人取消去银行。第三种是小q想询问他第x分钟去银行需要等多久。小q是个礼貌的人如果有人跟他同一时刻到达,他会让别人先。
Input
单组数就
第一行输入一个整数m,代表m个事件。
接下来m行输入3种操作之一。
+ x t代表第x时刻有客人到银行办理业务,用时t(1<=x,t<=10^6)
- i 代表第i个事件中的客人取消业务办理(1<=i<=m)
?x代表小q想知道如果他在时刻x去,要等多久(1<=x<=10^6)
30%数据:m<=1000
100%数据 m<=300000
Output
对于每个?事件输出一行,只包含一个整数,代表答案
SampleInput
19
? 3
+ 2 2
? 3
? 4
+ 5 2
? 5
? 6
+ 1 2
? 2
? 3
? 4
? 5
? 6
? 7
? 9
- 8
? 2
? 3
? 6
SampleOutput
0
1
0
2
1
3
2
1
2
1
0
0
2
1
1
样例解释:如果小q第3时刻来,前面没有人所以等待0.如果第3时刻来,前面有个客人为(2,2)第4时刻才结束,那么小q则需要等待1...
思路:
假设从j时刻开始,后面到的所有人都要开始排队,我们假设每个时刻总用时a[j](也就是题目中的t)
a[j]前缀和设为sum[j]
所以i时刻的排队时间为 sum[i] - sum[j] - (i - (j + 1))
那么怎么快速找到这个j呢?显然如果sum[i] - sum[j] < (i - (j + 1)),那就是不用排队,我们取0;如果sum[i] - sum[j] > (i - (j + 1)),那我们就找出 max(sum[i] - sum[j] - (i - (j + 1)))
综上,结果应是max(sum[i] - sum[j] - (i - (j + 1)),0) 1<=j<i,由于i确定,所以可以转化为 sum[i] - i + 1 + max(j - sum[j]),用线段树维护j - sum[j]的最大值和sum[i]
代码:
#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6 + ;
const ull seed = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
ll sum[maxn << ], Max[maxn << ], lazy[maxn << ];
int t[maxn], p[maxn], v[maxn];
void pushDown(int rt){
if(lazy[rt]){
lazy[rt << ] += lazy[rt];
lazy[rt << | ] += lazy[rt];
sum[rt << ] += lazy[rt];
sum[rt << | ] += lazy[rt];
Max[rt << ] -= lazy[rt];
Max[rt << | ] -= lazy[rt];
lazy[rt] = ;
}
}
void build(int l, int r, int rt){
if(l == r){
Max[rt] = l;
return;
}
int m = (l + r) >> ;
build(l, m, rt << );
build(m + , r, rt << | );
Max[rt] = max(Max[rt << ], Max[rt << | ]);
}
void update(int L, int R, int l, int r, int rt, ll v){
if(L <= l && R >= r){
lazy[rt] += v;
sum[rt] += v;
Max[rt] -= v;
return;
}
pushDown(rt);
int m = (l + r) >> ;
if(L <= m)
update(L, R, l, m, rt << , v);
if(R > m)
update(L, R, m + , r, rt << | , v);
Max[rt] = max(Max[rt << ], Max[rt << | ]);
}
ll queryMax(int L, int R, int l, int r, int rt){
if(R <= ) return ;
if(L <= l && R >= r){
return Max[rt];
}
pushDown(rt);
int m = (l + r) >> ;
ll MAX = -INF;
if(L <= m)
MAX = max(MAX, queryMax(L, R, l, m, rt << ));
if(R > m)
MAX = max(MAX, queryMax(L, R, m + , r, rt << | ));
Max[rt] = max(Max[rt << ], Max[rt << | ]);
return MAX;
}
ll querySum(int pos, int l, int r, int rt){
if(pos == ) return ;
if(l == r){
return sum[rt];
}
pushDown(rt);
int m = (l + r) >> ;
ll ans;
if(pos <= m)
ans = querySum(pos, l, m, rt << );
else
ans = querySum(pos, m + , r, rt << | );
Max[rt] = max(Max[rt << ], Max[rt << | ]);
return ans;
}
int main(){
int n, m;
int e = ;
build(, e, );
scanf("%d", &m);
for(int i = ; i <= m; i++){
char o[];
int x, tt;
scanf("%s", o);
if(o[] == '+'){
scanf("%d%d", &p[i], &v[i]);
update(p[i], e, , e, , v[i]);
}
else if(o[] == '-'){
scanf("%d", &x);
update(p[x], e, , e, , -v[x]);
}
else{
scanf("%d", &x);
ll SumI = querySum(x, , e, );
ll MaxJ = max(queryMax(, x - , ,e, ), 0LL);
printf("%lld\n", SumI - x + + MaxJ);
//sum[i] - sum[j] - (i - (j + 1))
//sum[i] - i + 1 + (j - sum[j])
}
}
return ;
}
/*
假设从j位置开始,后面所有人都要开始排队,每个位置用时a[j]
a[j]前缀和sum[j]
所以i位置排队 = sum[i] - sum[j] - (i - (j + 1))
*/
FJUT3701 这也是一道数论题(线段树)题解的更多相关文章
- FJUT-这还是一道数论题
这还是一道数论题 TimeLimit:4000MS MemoryLimit:128MB 64-bit integer IO format:%lld Special Judge Problem D ...
- [BJOI2019]删数(线段树)
[BJOI2019]删数(线段树) 题面 洛谷 题解 按照值域我们把每个数的出现次数画成一根根的柱子,然后把柱子向左推导,\([1,n]\)中未被覆盖的区间长度就是答案. 于是问题变成了单点修改值,即 ...
- P3939 数颜色 线段树动态开点
P3939 数颜色 线段树动态开点 luogu P3939 水.直接对每种颜色开个权值线段树即可,注意动态开点. #include <cstdio> #include <algori ...
- poj 3468 A Simple Problem with Integers(原来是一道简单的线段树区间修改用来练练splay)
题目链接:http://poj.org/problem?id=3468 题解:splay功能比线段树强大当然代价就是有些操作比线段树慢,这题用splay实现的比线段树慢上一倍.线段树用lazy标记差不 ...
- BZOJ2120&2453数颜色——线段树套平衡树(treap)+set/带修改莫队
题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...
- BZOJ 3813--奇数国(线段树&欧拉函数&乘法逆元&状态压缩)
3813: 奇数国 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 755 Solved: 432[Submit][Status][Discuss] ...
- Luogu5324 BJOI2019删数(线段树)
考虑无修改怎么做.对于1~n的每个数,若其存在,将最后一个放在其值的位置,剩余在其前面依次排列,答案即为值域1~n上没有数的位置个数.带修改显然记一下偏移量线段树改一改就好了. #include< ...
- POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释
http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...
- HDU 1556 Color the Ball 线段树 题解
本题使用线段树自然能够,由于区间的问题. 这里比較难想的就是: 1 最后更新须要查询全部叶子节点的值,故此须要使用O(nlgn)时间效率更新全部点. 2 截取区间不能有半点差错.否则答案错误. 这两点 ...
随机推荐
- 2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889
挺有意思的一套题,题也没有啥毒瘤了,本来是队切的结果种种原因大家全挂机了. 只补了百人题,一共7个,其他的暂时先不补了,,也不会嘛qwq H:签到 #include <bits/stdc++.h ...
- mysql日志分类
mysql的日志分类: (1)错误日志:记录mysql服务的启动,运行,停止mysql服务时出现的问题 [mysqld] log_error=[/path/filename] (2)通用查询日志:记录 ...
- td使用word-break: break-all;强制换行无效的解决
今天发现表格内容不换行,加了word-break: break-all;也没有效果,后来检查发现用户编辑的html内容包含了CSS,其中有一项: td {padding-top:1px;padding ...
- 泡泡一分钟:Cubic Range Error Model for Stereo Vision with Illuminators
Cubic Range Error Model for Stereo Vision with Illuminators 带有照明器的双目视觉的三次范围误差模型 "链接:https://pan ...
- vue computed的执行问题
1.在new Vue()的时候,vue\src\core\instance\index.js里面的_init()初始化各个功能 function Vue (options) { if (process ...
- 线程安全 Thread Safety Problem scala concurrency 并发
小结: 1.基于java并发模型 Scala concurrency is built on top of the Java concurrency model. 2. 将每个请求放入一个新的线程 T ...
- [efficiency] emacs入门
一. 没记错的话,这可能是第三次读emacs tutorial了.前两次读的非常慢,也不记得有没有读完了.总之最后都忘光了. 这次读的很顺畅,利用工作的空闲时间加上今天晚上(周日).总算是读完了. 没 ...
- GAN (Generative Adversarial Network)
https://www.bilibili.com/video/av9770302/?p=15 前面说了auto-encoder,VAE可以用于生成 VAE的问题, AE的训练是让输入输出尽可能的接近, ...
- MySQL 大表优化方案(长文)
当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...
- 万能poi导入功能模板
同时支持2007版本和2003版本,空行过滤,纯数字类型数据格式处理,日期格式处理等 package com.yss.db.util; import com.yss.base.common.excep ...