2017西安交大ACM小学期数据结构 [树状数组,极大值]
2017-07-03 19:05
381 查看
Problem D
发布时间: 2017年6月28日 10:51 最后更新: 2017年6月28日 16:38 时间限制: 1000ms 内存限制: 32M描述
给定一个长度为n的序列a1, a2,
..., an
当k满足2≤k≤n−1, ak>ak−1且ak>ak+1时, 将元素k称为极大值点,
给出q个操作,
操作分为两种
对于形如1 x y的操作,
将ax修改为y,
满足1≤x≤n, 1≤y≤109
对于形如2 x y的操作,
输出区间[x,y]内有多少个"极大值点",
满足1≤x≤y≤n
9×104≤n≤105, 9×104≤q≤105, 1≤ai≤109
输入
第一行两个整数n, q,
意义如上所述。
第二行n个整数,
表示序列a。
接下来q行,
每行第一个数为opt,
之后紧跟两个数, 意义如上所述。
输出
对于每个操作2,
输出答案, 一行一个。
样例输入1 复制
8 3 3 1 4 1 5 9 2 6 2 1 8 1 3 1 2 1 8
样例输出1
2 1
我们可以直接创建一个树状数组,如果某个元素x是极大值,那么我们就往蜀树状数组相应的位置写上1,这样的话,想要统计区间最大值的个数,只需要
统计树状数组的区间和就可以了。
而在维护的时候(修改a[x] 为y)要小心的考虑
这里举一个例子,要将a[x]改为y的情况
(1)如果修改前a[x]是极大值,修改后a[x]非极大值,那么add(x,-1)
(2)如果修改前a[x]非极大值,修改后a[x]为极大值,那add(x,-1)
(3).。。注意a[x]改成y不光影响x出的值,x-1,x+1处都有可能被影响
。。。要注意
代码:
#include <iostream> #include <cstdio> using namespace std; const int MAX = 1e5+7; int n,q; int a[MAX]; int b[MAX]; inline int lowbit(int x){ return x & (-x); } int getsum(int pos){ int res = 0; while(pos){ res += b[pos]; pos -= lowbit(pos); } return res; } void add(int pos,int val){ while(pos <= n){ b[pos] += val; pos += lowbit(pos); } } inline bool check(int pos){ return a[pos] > a[pos+1] && a[pos] > a[pos-1]; } int main(){ scanf("%d%d",&n,&q); for(int i = 1;i <= n;i++){ scanf("%d",&a[i]); } for(int i = 2;i < n;i++){ if(check(i)){ add(i,1); } } while(q--){ int opt; scanf("%d",&opt); if(opt == 1){ int x,y; scanf("%d%d",&x,&y); if(x == 1){ if(!check(2) && (a[2] > y && a[2] > a[3])){ add(2,1); } if(check(2) && !(a[2] > y && a[2] > a[3])){ add(2,-1); } } else if(x == n){ if(!check(n-1) && (a[n-1] > a[n-2] && a[n-1] > y)){ add(n-1,1); } if(check(n-1) && !(a[n-1] > a[n-2] && a[n-1] > y)){ add(n-1,-1); } } else{ if(!check(x) && (y > a[x-1] && y > a[x+1]) ){ add(x,1); } if(check(x) && !(y > a[x-1] && y > a[x+1]) ){ add(x,-1); } if(x >= 3 && !check(x-1) && (a[x-1] > a[x-2] && a[x-1] > y)){ add(x-1,1); } if(x >= 3 && check(x-1) && !(a[x-1] > a[x-2] && a[x-1] > y)){ add(x-1,-1); } if(x <= n-2 && !check(x+1) && (a[x+1] > a[x+2] && a[x+1] > y)){ add(x+1,1); } if(x <= n-2 && check(x+1) && !(a[x+1] > a[x+2] && a[x+1] > y)){ add(x+1,-1); } } a[x] = y; } else{ int x,y ;scanf("%d%d",&x,&y); printf("%d\n",getsum(y) - getsum(x-1)); } } return 0; }
相关文章推荐
- 2017西安交大ACM小学期数据结构 [树状数组]
- 2017西安交大ACM小学期数据结构 [树状数组 离散化]
- 2017西安交大ACM小学期数据结构 [线段树]
- 2017西安交大ACM小学期数据结构 [分块、二维矩阵]
- 2017西安交大ACM小学期数据结构 [分块,区间修改,单点查询]
- 2017西安交大ACM小学期数据结构 [又是树状数组、异或]
- 2017西安交大ACM小学期数论 [水题]
- 2017西安交大ACM小学期 美妙音乐[差分KMP匹配]
- 2017-2018 ACM-ICPC, NEERC Problem G Galactic Collegiate Programming Contest(树状数组)
- 计蒜客-2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛G题Query on a strin(树状数组+暴力更新)
- 2017西安交大ACM小学期 刁钻的顾客[3进制+折半枚举]
- 2017西安交大ACM小学期 敏感词汇[AC自动机]
- 2017西安交大ACM小学期数论 [完全平方数]
- 2017西安交大ACM小学期 毁灭序列[倒跑并查集]
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛Train Seats Reservation(树状数组的运用)
- 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string 【KMP+树状数组】
- 2017西安交大ACM小学期数论 [更新学号]
- HDU 6203 ping ping ping (LCA + 树状数组, 2017 ACM/ICPC Asia Regional Shenyang Online)
- 2017西安交大ACM小学期数论 [等差数列]
- 2017西安交大ACM小学期 神器插座 KMP匹配