博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[COGS 2065]学数数
阅读量:5327 次
发布时间:2019-06-14

本文共 2637 字,大约阅读时间需要 8 分钟。

2065. 学数数

★★★☆   输入文件:jxthree.in   输出文件:jxthree.out   简单对比

时间限制:1 s   内存限制:256 MB

【题目描述】

 

从前有一只咩,还有一只叽,还有……嗯……一只毒。

毒是咩和叽的师父。

咩经常算不对像3+0.5这样的数,它总认为3+0.5=5。叽经常算不对60+20这样的数,它总认为60+20=100。

所以毒为了锻炼它们数数的能力,想出了下面这个游戏:

毒先在纸上写下n个数a1,a2,…,an,然后咩和叽会找出所有的连续子数组(共有n*(n+1)/2个),在自己的纸上记录下每个连续子数组的最大值,那之后毒会给

咩和叽Q个问题,每个问题形如下面三种之一:

1.记录的数中有多少个大于K?

2.记录的数中有多少个等于K?

3.记录的数中有多少个小于K?

然而这只咩太蠢了,总是答错毒的问题,咩很伤心,请你帮帮它吧!

 

【输入格式】

 

第一行两个整数n,Q。

第二行n个整数a1,a2,…,an。

下面Q行,每行有一个字符op和一个整数K。

如果op是“>”,说明是第一种问题。

如果op是“=”,说明是第二种问题。

如果op是“<",说明是第三种问题

 

【输出格式】

共有Q行,第i行表示第i个问题的答案。

【样例输入】

3  5

1  2  3

>  1

<  2

=  3

>  4

<  5

【样例输出】

5

1

3

0

6

【提示】

 

 咩和叽的纸上应该写着1,2,2,3,3,3。

  数据范围与约定

 对于20%的数据,1≤n≤200,1≤Q≤200,1≤ai,K≤10^6。

 对于40%的数据,1≤n≤5000,1≤Q≤5000,1≤ai,K≤10^6。

 对于60%的数据,1≤n≤10^5,1≤Q≤10^5,1≤ai,K≤10^6,ai两两不同。

 对于80%的数据,1≤n≤10^5,1≤Q≤10^5,1≤ai,K≤10^6。

 对于100%的数据,1≤n≤10^5,1≤Q≤10^5,1≤ai,K≤10^9。

题解

我们大概可以注意到, 以某个数为最大值的最大连续子数组的左右端点都会延伸到比该数大的第一个数的右/左边, 而连续子数组的个数就等于它向右延伸的个数乘以向左延伸的个数. 所以我们可以预处理出这个左右端点(或者左/右边第一个比它大的数的位置), 然后对它求前缀和, 按需响应查询就可以了

而至于左右端点的预处理, 我们首先对它进行离散化, 然后使用树状数组( $O(nlog(n))$ )或者单调栈( $O(n)$ )分别从两个方向扫描一遍来处理.

然后就是注意区间要左闭右开防止重复计数

参考代码

这里是单调栈的版本

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 8 const int MAXN=100010; 9 10 int n;11 int q;12 int* sed;13 int a[MAXN];14 int b[MAXN];15 int s[MAXN];16 int l[MAXN];17 int r[MAXN];18 long long cnt[MAXN];19 20 void Initialize();21 template
void Clear(T&);22 23 int main(){24 Initialize();25 int tmp;26 char buf[5];27 for(int i=1;i<=n;i++){28 tmp=std::lower_bound(s+1,sed,a[i])-s;29 cnt[tmp]+=1ll*(i-l[i]+1)*(r[i]-i+1);30 }31 for(int i=2;i<=n;i++){32 cnt[i]+=cnt[i-1];33 }34 while(q--){35 scanf("%s%d",buf,&tmp);36 if(*buf=='>'){37 int x=std::upper_bound(s+1,sed,tmp)-s;38 printf("%lld\n",cnt[sed-s-1]-cnt[x-1]);39 }40 else if(*buf=='='){41 int x=std::lower_bound(s+1,sed,tmp)-s;42 printf("%lld\n",s[x]==tmp?(cnt[x]-cnt[x-1]):0);43 }44 else if(*buf=='<'){45 int x=std::lower_bound(s+1,sed,tmp)-s;46 printf("%lld\n",cnt[x-1]);47 }48 }49 return 0;50 }51 52 void Initialize(){53 freopen("jxthree.in","r",stdin);54 freopen("jxthree.out","w",stdout);55 scanf("%d%d",&n,&q);56 for(int i=1;i<=n;i++){57 scanf("%d",a+i);58 s[i]=a[i];59 }60 std::sort(s+1,s+n+1);61 sed=std::unique(s+1,s+n+1);62 std::stack
s;63 for(int i=1;i<=n;i++){64 while(!s.empty()&&a[s.top()]<=a[i])65 s.pop();66 l[i]=s.empty()?1:s.top()+1;67 s.push(i);68 }69 Clear(s);70 for(int i=n;i>0;i--){71 while(!s.empty()&&a[s.top()]
void Clear(T& x){79 T tmp;80 std::swap(tmp,x);81 }
Backup

 

 

转载于:https://www.cnblogs.com/rvalue/p/7661000.html

你可能感兴趣的文章
Linux 的 date 日期的使用
查看>>
PHP zip压缩文件及解压
查看>>
SOAP web service用AFNetWorking实现请求
查看>>
Java变量类型,实例变量 与局部变量 静态变量
查看>>
mysql操作命令梳理(4)-中文乱码问题
查看>>
Python环境搭建(安装、验证与卸载)
查看>>
一个.NET通用JSON解析/构建类的实现(c#)
查看>>
Windows Phone开发(5):室内装修 转:http://blog.csdn.net/tcjiaan/article/details/7269014
查看>>
详谈js面向对象 javascript oop,持续更新
查看>>
关于这次软件以及pda终端的培训
查看>>
jQuery上传插件Uploadify 3.2在.NET下的详细例子
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
正则表达式的用法
查看>>
线程安全问题
查看>>
SSM集成activiti6.0错误集锦(一)
查看>>
个人作业
查看>>
下拉刷新
查看>>
linux的子进程调用exec( )系列函数
查看>>
MSChart的研究
查看>>