6.21的评论,6.20在搞学校工作,唉,训练还是得抓紧的
G. Count the Trains链接思考了很久,但还是想不到怎么维护一些数据来达到每次更新的时候怎么快速求答案.一直在思考修改 i i i的位置,对原数组 a i − 1 , a i + 1 a_{i-1},a_{i+1} ai−1,ai+1和根据题目定义的数组 b i + 1 b_{i+1} bi+1的影响,可以发现,修改 i i i并不会影响 i i i位置之前的答案贡献,但对 b i + 1 b_{i+1} bi+1后面有影响.如果 b i + 1 b_{i+1} bi+1的值没有变化,那答案只会在 a i − 1 a_{i-1} ai−1那里有贡献,如果有变化,那么肯定是变得更小,那么就会使得后边的一些元素 b j > b i + 1 b_j>b_{i+1} bj>bi+1通通变成 b i + 1 b_{i+1} bi+1。这部分答案的贡献就是这些 b j b_j bj的数目。 那么问题来了,咋快速求呢,不会。 搬运标程了:用 b 数 组 代 表 映 射 完 毕 后 的 a 数 组 b数组代表映射完毕后的a数组 b数组代表映射完毕后的a数组开一个set,保存那些连续段的起始坐标,也就是保存坐标 i i i,如果有 b i < b i − 1 b_ia_{mx},mx是集合S里面的最大值,代表上一个答案的下标 aj>amx,mx是集合S里面的最大值,代表上一个答案的下标,那么就会形成一个新的断点,需要我们把 j j j插入里面去. 当修改 a i a_i ai的时候,需要把所有 j > i 且 a j > a i j>i且a_j>a_i j>i且aj>ai的 j j j从集合中全部删去. 在集合S里面, 下 标 j 越 大 , 原 数 组 对 应 的 a j 也 就 越 小 下标j越大,原数组对应的a_j也就越小 下标j越大,原数组对应的aj也就越小.然后修改后的 a j 与 下 标 j a_j与下标j aj与下标j考虑是否能插入回原数组, 条件1: j j j下标原本就在这个集合里面了. 条件2: j j j下标不在,但修改后的 a j a_j aj比集合的前一个元素要小, 满足这两个条件之一就可以了.所以可以直接二分找到自己,比较二分指针前一个的值就能判断当前的值是否需要插入. 对于删除的操作,就是删掉所有 k > j 且 a k > a j k>j且a_k>a_j k>j且ak>aj。 代码技巧:用rbegin代表迭代器最后一个元素,用prev(it)函数,找迭代器it的上一个.
#include
using namespace std;
const int maxn = 1e6+5;
const int INF = 1e9+7;
typedef long long ll;
typedef pair pii;
#define all(a) (a).begin(), (a).end()
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;cin>>T;
while(T--){
int n,m;cin>>n>>m;
vector a(n+1,0);
for(int i=1;i>a[i];
set S;
for(int i=1;ia[i]){
S.insert(i);
}
}
while(m--){
int j,d;cin>>j>>d;
a[j]-=d;
auto it = S.upper_bound(j);
if(it!=S.begin()){
it = prev(it);
if(*it==j||a[*it]>a[j]) S.insert(j);
}
else S.insert(j);
while(true){
it = S.upper_bound(j);
if(it!=S.end()&&a[*it]>=a[j]) S.erase(it);
else {
break;
}
}
cout
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?