CDOJ 1157 数列(seq) 分块+线段树
数列(seq)
Time Limit: 1 Sec
Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/problem/show/1157
Description
给出一个长度为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
5 3
1
3
2
3
2
Q 1
C 1 3
Q 1
Sample Output
2
4
HINT
对于40%的数据,n、m<=5000
对于100%的数据,n、m<=50000,|Ai|、x<=100000
题意
题解:
简单分析一下,就知道,他是让你求有多少个数在他右边比他小
然后再求一个不递减的序列长度
假设,ans[x]表示以a[x]开头的单调不减序列的长度的话
如果查询的位置是x的话,有y个数在他右边比他小,那么答案就是y+ans[y+1]
--------------------
具体做法的话:
如果不分块的话,根本不会……
右边有多少个比他小的,就用线段树来二分就好了
不递减的序列长度,就用分块来维护就好了
@)1%KBO0HM418$J94$1R.jpg)
代码:
//qscqesze
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200006
#define mod 1000000007
#define eps 1e-9
#define e exp(1.0)
#define PI acos(-1)
#define lowbit(x) (x)&(-x)
const double EP = 1E- ;
int Num;
//const int inf=0x7fffffff;
const ll inf=;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
//************************************************************************************* int n;
int a[maxn]; struct data{
int l,r,mn;
}tr[maxn*];
void build(int k,int s,int t)
{
tr[k].l=s;tr[k].r=t;
if(s==t){tr[k].mn=a[s];return;}
int mid=(s+t)>>;
build(k<<,s,mid);
build(k<<|,mid+,t);
tr[k].mn=max(tr[k<<].mn,tr[k<<|].mn);
}
int ask(int k,int s,int t)
{
int l=tr[k].l,r=tr[k].r;
if(s==l&&t==r)return tr[k].mn;
int mid=(l+r)>>;
if(t<=mid)return ask(k<<,s,t);
if(s>mid)return ask(k<<|,s,t);
return max(ask(k<<,s,mid),ask(k<<|,mid+,t));
}
void update(int k,int x,int y)
{
int l=tr[k].l,r=tr[k].r;
if(l==r){tr[k].mn=y;return;}
int mid=(l+r)>>;
if(x<=mid)update(k<<,x,y);
if(x>mid)update(k<<|,x,y);
tr[k].mn=max(tr[k<<].mn,tr[k<<|].mn);
} int l[],r[];
int belong[];
int block;
vector<int> Q[];
int ans[maxn];
int num;
int main()
{
n = read();
int q=read();
for(int i=;i<=n;i++)
a[i]=read();
block = sqrt(n);
int 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+; for(int i=;i<=num;i++)
{
int tmp = ;
for(int j=l[i];j<=r[i];j++)
{
if(a[j]>=tmp)
{
Q[i].push_back(a[j]);
tmp = a[j];
}
}
} build(,,n);
char c[];
while(q--)
{
scanf("%s",c);
if(c[]=='Q')
{
int x=read();
int L = x+ , R = n;
while(L<=R)
{
int mid = (L+R)>>;
if(ask(,x+,mid)<=a[x])
L = mid+;
else
R = mid-;
}
//cout<<l<<endl;
ans[x] = L - x - ;
int x2=ans[x]++x;
int k = belong[x2];
int tmp = a[x2];
int Ans = ;
if(x2!=n+){
for(int i=x2;i<=r[k];i++)
{
if(a[i]>=tmp)
{
Ans++;
tmp = a[i];
}
}
for(int i=k+;i<=num;i++)
{
if(!Q[i].empty())
{
if(tmp>Q[i][Q[i].size()-])
continue;
Ans+=Q[i].end()-lower_bound(Q[i].begin(),Q[i].end(),tmp);
tmp = Q[i][Q[i].size()-];
}
}
}
printf("%d\n",Ans + ans[x]);
}
else
{
int x=read();
int y=read();
a[x]=y;
update(,x,y);
int k = belong[x];
Q[belong[x]].clear();
int tmp = ;
for(int i=l[k];i<=r[k];i++)
{
if(a[i]>=tmp)
{
Q[k].push_back(a[i]);
tmp = a[i];
}
}
}
}
}
CDOJ 1157 数列(seq) 分块+线段树的更多相关文章
- CDOJ 1292 卿学姐种花 暴力 分块 线段树
卿学姐种花 题目连接: http://acm.uestc.edu.cn/#/problem/show/1292 Description 众所周知,在喵哈哈村,有一个温柔善良的卿学姐. 卿学姐喜欢和她一 ...
- BZOJ5286 HNOI/AHOI2018转盘(分块/线段树)
显然最优走法是先一直停在初始位置然后一次性走完一圈.将序列倍长后,相当于找一个长度为n的区间[l,l+n),使其中ti+l+n-1-i的最大值最小.容易发现ti-i>ti+n-(i+n),所以也 ...
- [LuoguP1438]无聊的数列(差分+线段树/树状数组)
\(Link\) \(\color{red}{\mathcal{Description}}\) 给你一个数列,要求支持单点查询\(and\)区间加等差数列. \(\color{red}{\mathca ...
- [cogs2638]数列操作ψ(双标记线段树)
题目大意:给定一个数列a,你需要支持的操作:区间and,区间or,询问区间最大值 解题关键: 1.双标记线段树,注意优先级(超时) 当涉及多重标记时,定义出标记的优先级,修改操作时用优先级高(先下放) ...
- BZOJ - 2957 (分块/线段树)
题目链接 本质是维护斜率递增序列. 用分块的方法就是把序列分成sqrt(n)块,每个块分别用一个vector维护递增序列.查询的时候遍历所有的块,同时维护当前最大斜率,二分找到每个块中比当前最大斜率大 ...
- bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1798 [题意] 给定一个序列,要求提供区间乘/加,以及区间求和的操作 [思路] 线段树 ...
- 2018.07.31cogs2964. 数列操作η(线段树)
传送门 线段树基本操作. 给出一个排列b,有一个初始值都为0的数组a,维护区间加1,区间统计区间∑(ai/bi)" role="presentation" style=& ...
- bzoj 维护序列seq(双标记线段树)
Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 4184 Solved: 1518[Submit][Status][Discus ...
- 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq(线段树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1798 之前写了个快速乘..........................20多s...... 还好 ...
随机推荐
- Android开发之View动画效果插补器Interpolator
插补器Interpolator 官网描述:An interpolator defines the rate of change of an animation. This allows the bas ...
- Jquery动画第二部分
效果图: →→→→→→ <%@ Page Language="C#" AutoEventWireup="true" CodeFile=" ...
- bzoj3157 3516
太神了,被数学题虐了 orz http://m.blog.csdn.net/blog/skywalkert/43970331 这道题关键是抓住m较小的特点,构造递推解决 ; ..,..] of lon ...
- 【App FrameWork】框架的页面布局
之前主要用JqueryMobile+PhoneGap的模式开发移动应用,但JQueryMobile自身存在的硬伤太多,如加载速度缓慢,页面转场白屏.闪烁,头尾部导航浮动问题,页面滚动等等,用户体验效果 ...
- [ACdream 1099] 瑶瑶的第K大
瑶瑶的第K大 Time Limit: 4000/2000MS (Java/Others) Memory Limit: 256000/128000KB (Java/Others) Problem Des ...
- a标签中的label在IE下触发不了a标签的href链接(label标签——解析)
<a href="http://www.baidu.com/" target="_blank"> <span>百度</span&g ...
- C# 中的数组(array)
原文 C# 中的数组(array) 特性 数组是一个无序的元素序列.数组元素存储在一个连续性的内存块中,并可使用一个整数索引来访问. C# 声明数组变量时,数组的大小不是声明的一部分.这点与C/C++ ...
- windows 下Python import 导入自定义模块
周末在家研究这个东西,则找到解决方案. 费话少说,上代码 #定义一个自定义的函数,如下 #函数的名称必须是字母和数字的组合,不能用数字开头 #函数名后用小括号括住入参,可以用逗号分隔多个 #如果有返回 ...
- IO_REMOVE_LOCK使用方法小结(转载加改正)
原文链接:http://www.programlife.net/io_remove_lock.html IO_REMOVE_LOCK(删除锁)的具体结构没有公开,WDK的文档中中查不到IO_REMOV ...
- ubuntu修改主机名和出现问题
修改主机名方法,修改/etc/hostname即可,但是修改完成后,每次sudo都出现警告,警告解决方法如下: Linux 环境, 假设这台机器名字叫dev(机器的hostname), 每次执行sud ...