分块+二分,统计对数 CDOJ
http://acm.uestc.edu.cn/#/problem/show/1157
数列(seq)
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 128000/128000KB (Java/Others)
给出一个长度为n的数列A。现有如下两种操作:
修改操作:把数列中第i个数改为x
询问操作:给定一个位置i,问数列中有多少个位置j ( j>i ),满足位置i与位置j间所有的数都不超过Ai与Aj的较大值。
现共有m个操作,请对每个询问操作做出回答。
Input
第一行两个正整数n、m。
随后n行,每行一个正整数Ai。
随后m行,若是修改操作,则以一个大写C开头,随后两个正整数i和x;若是查询操作,则以一个大写Q开头,随后一个正整数i。
Output
每行一个整数,依次对每个询问操作给出回答。
Sample input and output
| Sample Input | Sample Output |
|---|---|
5 3 |
2 |
Hint
对于40%的数据,n、m<=5000
对于100%的数据,n、m<=50000,|Ai|、x<=100000
思路:
这种xjb更新的,一般就是分块了
首先分析题目以后发现,对于区间[i,j],其中(i,j)之间所有的数值都是小于max(a[i], a[j])的。然后我们又可以发现,每一个数值a[i],其都会维护一个区间(即[x, i]),且[x,i]中的所有数值都<=a[i]。
修改、更新操作:
接下来我们分块,对于每个块,我们维护块中的最大值(用maxval纪律)和 块中的每个position能延伸到块的左边界的数(将这个数值放到vector里面去),之所以要延伸到最左端,是因为只有能够延伸到最左端的才有资格让[x,j]区间内所有的数值都小于max(a[x],a[j])。 所以这一步的复杂度为sqrt(n)
询问操作:
左区间,暴力:
如果Max == a[x],那么把所有的a[i] <=a[x]的都ans++,
不然的话,只有a[i]>= Max,才能ans++
中间块的话,
①
如果maxval=a[x],那么就判断是否>=maxval[i]
if (true) ans+=目前块的大小
else 暴力目前的块
如果Max == a[x],同左区间的分类讨论
②如果maxval>a[x],那么我们就二分即可,看看有多少能连接到左边界
右区间,暴力:
同左区间。
所以这里的复杂度为sqrt(n) * log(n)
总的复杂度为O(m * sqrt(n) * log(n))
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
/*
对于某个数,我们要知道他到块的左端的所有数值都是比他小的才行
我们可以知道,每个position,向左边都可以维护一个特定的区间,
然后我们对块中,看看有哪些能够维护到左边界的,并且放到vector里面排序,而且
放入vector里面的顺序一定是有序的,
因此,上面是修改操作,复杂度为sqrt(n) 对于询问操作,我们每次就只需要判断即可,对于边缘的块,我们暴力
对于完整的块,我们二分即可。所以总的复杂度为sqrt(n) * log(n)。
*/
const int inf = 0x3f3f3f3f;
const int maxn = + ;
int n, m;
int a[maxn];
int num, block, belong[maxn], l[maxn], r[maxn];
int maxval[maxn];//目前块的最大值
vector<int> ve[maxn];//目前该块能到最左边的有几个 void build(){
block = sqrt(n); num = n / block;
if (n % block) num++;
for (int i = ; i <= num; i++){
l[i] = (i - ) * block + , r[i] = i * block;
}
r[num] = n;
for (int i = ; i <= n; i++)
belong[i] = (i - ) / block + ;
} void update(int be){
int Max = -inf;
ve[be].clear();
for (int i = l[be]; i <= r[be]; i++){
if (a[i] >= Max) {
ve[be].push_back(a[i]); Max = a[i];
}
}
maxval[be] = Max;
} int query(int x, int y){
int ans = , Max = a[x];
if (belong[x] == belong[y]){
for (int i = x + ; i <= y; i++){
if (a[i] >= Max) {Max = a[i]; ans++;}
else if(a[x] == Max) ans++;
}
return ans;
}
for (int i = x + ; i <= r[belong[x]]; i++){
if (a[i] >= Max){Max = a[i]; ans++;}
else if(a[x] == Max) ans++;
}
//printf("ans = %d\n", ans);
for (int i = belong[x] + ; i < belong[y]; i++){
if (a[x] == Max){
if (Max >= maxval[i]) ans += r[i] - l[i] + ;
else {
for (int j = l[i]; j <= r[i]; j++){
if (a[j] >= Max) {Max = a[j]; ans++;}
else if(a[x] == Max) ans++;
}
}
}
else {
int pos = lower_bound(ALL(ve[i]), Max) - ve[i].begin() + ;
ans += ve[i].size() + - pos;
Max = max(Max, maxval[i]);
}
}
//printf("ans = %d\n", ans);
for (int i = l[belong[y]]; i <= y; i++){
if (a[i] >= Max){Max = a[i]; ans++;}
else if(a[x] == Max) ans++;
}
//printf("ans = %d\n", ans);
return ans;
} int main(){
cin >> n >> m;
for (int i = ; i <= n; i++) scanf("%d", a + i);
build();
for (int i = ; i <= num; i++){
update(i);
}
while (m--){
char ch[]; int i, x;
scanf("%s%d", ch, &i);
if (ch[] == 'C'){
scanf("%d", &x); a[i] = x;
update(belong[i]);
}
else {
printf("%d\n", query(i, n));
}
}
return ;
}
/*
10 1
9284 15645 17127 23946 2177 12658 9740 29482 24450 25110
Q 4
ans = 4
*/
分块+二分,统计对数 CDOJ的更多相关文章
- BZOJ_3343_教主的魔法_分块+二分查找
BZOJ_3343_教主的魔法_分块+二分查找 题意:教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列被编号为 ...
- 【bzoj2957】楼房重建 分块+二分查找
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子.为了简化问题,我们考虑这些事件发生在一个二 ...
- 【bzoj2453】维护队列/【bzoj2120】数颜色 分块+二分
题目描述 你小时候玩过弹珠吗? 小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N.为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少.当然,A有时候会依据个人喜好, ...
- 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分
题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...
- BZOJ 3343: 教主的魔法(分块+二分查找)
BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1172 Solved: ...
- Bzoj 3343: 教主的魔法(分块+二分答案)
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MB Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息 ...
- 【BZOJ3343】教主的魔法 分块+二分
Description 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.…….N. 每个人的 ...
- 【tyvj1463】智商问题 [分块][二分查找]
Background 各种数据结构帝~各种小姊妹帝~各种一遍AC帝~ 来吧! Description 某个同学又有很多小姊妹了他喜欢聪明的小姊妹 所以经常用神奇的函数来估算小姊妹的智商他得出了自己所有 ...
- 分块+二分 BZOJ 3343
3343: 教主的魔法 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1312 Solved: 585[Submit][Status][Discus ...
随机推荐
- Beta阶段第2周/共2周 Scrum立会报告+燃尽图 02
此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2410] 版本控制地址 https://git.coding.net ...
- P4语法(5) Package
Package 对于package这个概念,类似于将一个框架中各组成部件以一个规律进行打包,以正常运转. 基于一个架构去编写一个新的pipeline的时候,需要先了解初始化的时候需要提供那些东西,pa ...
- OA_1界面
<%@ page language="java" contentType="text/html;charset=GB18030" pageEncoding ...
- RovingUI组件库-包含堆栈式通知提醒框(Toast)的小程序组件库
RovingUI是个人在开发小程序过程中将用到的组件集合而成的一个UI库,包含一些基本通用组件(按钮.栅格.通用样式.徽标.通知和面包屑). 源起得归于我在开发中没有找到现成的堆栈式提醒框(比如ant ...
- DS01--抽象数据类型
一.作业内容 二.数据结构.函数说明 1.头文件 common.h 2.数据结构 Rational.h 三.代码实现说明 1.构造有理数T 2.销毁有理数T 3.e返回有理数的分子或分母 4.用e改变 ...
- Ribbon源码解析
SpringCloud中的Ribbon开源项目,提供了客户端的负载均衡算法.这篇文章,我们来介绍下他是如何实现的.为了方便理解,我们以客户端调用的流程来介绍,其中会穿插介绍相关源代码. 简单回顾下Ri ...
- css & text-overflow & ellipsis
css & text-overflow & ellipsis https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflo ...
- 【ASP.NET 框架系列】您所经历的,但未必研究的那些技术
本篇文章更适合具有一定开发经验,一定功底,且对底层代码有所研究的朋友!!! 本篇文章稍微偏原理且底层,有一定难度和且比较晦涩,文章粒度稍微粗些,更细粒度的,会在后续的文章中,结合具体的Demo实 ...
- bzoj3477[Usaco2014 Mar]Sabotage
题意 给出一个长为n的正整数序列(n<=1e5),要求选出一个非空前缀和一个非空后缀(这两段不能够加起来组成整个序列),使得这个前缀和后缀中的所有数字一起求平均数的结果最小 分析 最大/最小化平 ...
- 洛谷 P2146 [NOI2015]软件包管理器
真没有想到,这竟然会是一道NOI的原题,听RQY说,这套题是北大出的,北大脑抽认为树剖很难... 只恨没有早学几年OI,只A这一道题也可以出去吹自己一A了NOI原题啊 好了,梦该醒了,我们来看题 以后 ...