题意(FJUT翻译HDU):

钱陶陶家门前有一棵苹果树。 秋天来了,树上的n个苹果成熟了,淘淘会去采摘这些苹果。

到园子里摘苹果时,淘淘将这些苹果从第一个苹果扫到最后一个。 如果当前的苹果是第一个苹果,或者它严格高于之前选择的苹果,那么淘淘将采摘这个苹果; 否则,他不会选择。

题目来了:已知这些苹果的高度为h1,h2,⋯,hn,您需要回答一些独立的查询。 每个查询是两个整数p,q,表示如果第p个苹果的高度修改为q,询问当前淘淘将摘到的苹果的数量。 你能解决这个问题吗?

思路:pre表示1~i的最大连续答案,tail代表i~n的最大连续答案。最终答案为p前,p,p后三部分的贡献和。

预处理pre和tail。tail从后往前预处理,用二分(线段树)查找第一个比i位置大的数。

然后每次找p前最大值下标preMax,ans += pre[preMax],为p前贡献。

ans += q > a[preMax],为p的贡献。

查找p后第一个大于前面所有数的值的下标tailMax,ans += tail[tailMax],为p后贡献。

三者贡献和为总贡献。

二分查找p后第一个大于前面所有数的值的下标一顿好写啊(微笑

思考了半天发现是线段树写错了。显然(?)只有在L <= l && R >= r(就是说当前区间是查询区间子集)才能直接剪枝选择左儿子或者右儿子。

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const ll INF = 0x3f3f3f3f;
int n;
ll a[maxn];
ll pre[maxn], tail[maxn], Max[maxn << ];
//1~i最多递增,i~n最多递增
void build(int l, int r, int rt){
if(l == r){
Max[rt] = a[l];
return;
}
int m = (l + r) >> ;
build(l, m, rt << );
build(m + , r, rt << | );
Max[rt] = max(Max[rt << ], Max[rt << | ]);
}
int tailMax, preMax;
void queryPre(int l, int r, int L, int R, int rt){
if(R == ) return;
if(l == r){
if(a[l] > a[preMax]) preMax = l;
return;
}
int m = (l + r) >> ;
if(L <= l && R >= r){
if(Max[rt << ] > Max[rt << | ])
queryPre(l, m, L, R, rt << );
else
queryPre(m + , r, L, R, rt << | );
return;
}
if(L <= m)
queryPre(l, m, L, R, rt << );
if(R > m)
queryPre(m + , r, L, R, rt << | );
}
void queryTail(int l, int r, int L, int R, int rt, ll v){
if(L == n + ) return;
if(l == r){
if(Max[rt] > v) tailMax = min(l, tailMax);
return;
}
int m = (l + r) >> ;
if(L <= l && R >= r){
if(Max[rt << ] > v){
queryTail(l, m, L, R, rt << , v);
}
else if(Max[rt << | ] > v){
queryTail(m + , r, L, R, rt << | , v);
}
return;
}
if(Max[rt << ] > v && L <= m){
queryTail(l, m, L, R, rt << , v);
}
if(Max[rt << | ] > v && R > m){
queryTail(m + , r, L, R, rt << | , v);
}
}
int main(){
int m, T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n ,&m);
ll u = ;
pre[] = ;
a[] = ;
for(int i = ; i <= n; i++){
scanf("%lld", &a[i]);
if(a[i] > u){
u = a[i];
pre[i] = pre[i - ] + ;
}
else{
pre[i] = pre[i - ];
}
}
build(, n, );
for(int i = n; i >= ; i--){
tailMax = INF;
queryTail(, n, i + , n, , a[i]);
if(tailMax == INF) tail[i] = ;
else tail[i] = + tail[tailMax];
}
while(m--){
int p;
ll q;
scanf("%d%lld", &p, &q);
ll ans = ;
preMax = ;
queryPre(, n, , p - , );
ans += pre[preMax];
if(q > a[preMax]){
ans += ;
}
tailMax = INF;
queryTail(, n, p + , n, , max(a[preMax], q));
if(tailMax != INF) ans += tail[tailMax];
printf("%lld\n", ans);
}
}
return ;
}

HDU 6406 Taotao Picks Apples & FJUT3592 做完其他题后才能做的题(线段树)题解的更多相关文章

  1. [乱搞]hdu 6406 Taotao picks apples 笛卡尔树+倍增

    题目链接 Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n app ...

  2. hdu 6406 Taotao Picks Apples 线段树 单点更新

    Taotao Picks Apples Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

  3. hdu 6406 Taotao Picks Apples (线段树)

    Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n apples o ...

  4. hdu 6406 Taotao Picks Apples (2018 Multi-University Training Contest 8 1010)(二分,前缀和)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6406 思路: 暴力,预处理三个前缀和:[1,n]桃子会被摘掉,1到当前点的最大值,1到当前点被摘掉的桃子的 ...

  5. HDU 6406 Taotao Picks Apples 线段树维护

    题意:给个T,T组数据: 每组给个n,m:n个数,m个操作: (对序列的操作是,一开始假设你手上东西是-INF,到i=1时拿起1,之后遍历,遇到比手头上的数量大的数时替换(拿到手的算拿走),问最后拿走 ...

  6. HDU - 6406 Taotao Picks Apples (RMQ+dp+二分)

    题意:N个高度为hi的果子,摘果子的个数是从位置1开始从左到右的严格递增子序列的个数.有M次操作,每次操作对初始序列修改位置p的果子高度为q.每次操作后输出修改后能摘到得数目. 分析:将序列分为左.右 ...

  7. 【杂题总汇】HDU-6406 Taotao Picks Apples

    [HDU 6406]Taotao Picks Apples 多校赛的时候多写了一行代码就WA了……找了正解对拍,在比赛结束后17分钟AC了

  8. hdu6406 Taotao Picks Apples(线段树)

    Taotao Picks Apples 题目传送门 解题思路 建立一颗线段树,维护当前区间内的最大值maxx和可摘取的苹果数num.最大值很容易维护,主要是可摘取的苹果数怎么合并.合并左右孩子时,左孩 ...

  9. 多校 1010 Taotao Picks Apples(补题)

    >>点击进入原题<< 思路:题解很有意思,适合线段树进阶 考虑每次修改不叠加,因此我们可以从如何对原序列进行预处理着手.通过观察可以发现,将原序列从任意位置断开,我们可以通过分 ...

随机推荐

  1. tfs分支操作

    1.在代码管理器中找到代码项 右击——分支与合并——分支——默认所有选项——确定. 2.可能刚打出的分支为红色,签入,修改代码,待测试后代码合并到主干中(下拉选出他的上级,一般为主干),删除分支. 3 ...

  2. python 爬起点目录

    #目标:书名,简介,作者,字数 #首先确定源代码的列表 import urllib.request import re from bs4 import BeautifulSoup import ran ...

  3. Robot Framework 教程 (3) - Resource及关键字 的使用

    From:http://www.cnblogs.com/buaawp/p/4754399.html Robot Framework 教程 (3) - Resource及关键字 的使用 在进行软件自动化 ...

  4. (Review cs231n) Backpropagation and Neural Network

    损失由两部分组成: 数据损失+正则化损失(data loss + regularization) 想得到损失函数关于权值矩阵W的梯度表达式,然后进性优化操作(损失相当于海拔,你在山上的位置相当于W,你 ...

  5. tensorflow学习4-过拟合-over-fitting

    过拟合: 真实的应用中,并不是让模型尽量模拟训练数据的行为,而是希望训练数据对未知做出判断. 模型过于复杂后,模型会积极每一个噪声的部分,而不是学习数据中的通用 趋势.当一个模型的参数比训练数据还要多 ...

  6. 转:Process类的使用

    转载自:http://www.oschina.net/code/snippet_119226_6188 一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 ...

  7. PHP $_SERVER 及用户真实IP

    $_SERVER 是一个包含了诸如头信息(header).路径(path).以及脚本位置(script locations)等等信息的数组.这个数组中的项目由 Web 服务器创建.不能保证每个服务器都 ...

  8. easyui datagrid 遇到的坑 cannot read property ·· pageNum bug and so on

    1 本人刚刚接到一个bug,就是初始化时若设置了datagrid到指定页数,点击下一页显示不对,4 --> ‘4’+1=41的字符串形式,再点击超出页码范围直接到最后一页: 原因:因为 page ...

  9. 每日linux命令学习-grep模式检索

    grep模式检索指令包括grep,egrep,和fgrep,.Linux系统使用正则表达式优化文本检索,所以在此,笔者首先学习了一下正则表达式. 1. 正则表达式 正则表达式使用被称为元字符(Meta ...

  10. JDBC和servlet设计思路、DAO模式思路、MVC思路粗略总结

    #JDBC和Servlet联合起来使用的项目思路: 说明:建库,最好一开始设置utf8字符集 step1: 在数据库中建表 如   create table t_user{ ...... } step ...