链接:http://acm.hdu.edu.cn/showproblem.php?pid=6406

思路:

暴力,预处理三个前缀和:【1,n】桃子会被摘掉,1到当前点的最大值,1到当前点被摘掉的桃子的数量,然后我们枚举修改p点造成的所有影响,:

1,假如新输入的点比原先的点的值更大,那么我们对修改后p这个点的值和【1,p-1】的最大值关系进行分析,也就是分析前半段的影响:(1)如果p点大于1-p-1的最大值的时候我们直接利用前缀和O(1)得到【1,p-1】有多少个桃子被摘掉,然后加上当前这个。(2)如果p点小于等于【1,p-1】的最大值时,对前半段和后半段都不会造成影响,直接输出预处理的到的【1,n】的值就好了;然后我们分析后半段的影响:(1)如果p点大于【1,p-1】的最大值,那么后半段中只有被摘掉的桃子会受到影响,我们直接二分找到【p+1,n】中被摘掉的桃子的值大于被修改后的值c的下标,减一下,就得出了,后半段会被摘掉的桃子中有几个在p点被修改后依旧需要摘掉,将后半段的值与前半段的值加起来就好了。(2)如果p点小于等于【1,p-1】的最大值,那么后半段不造成影响,

2.假如新输入的点小于等于原先的点值,依旧对修改后p这个点的值和【1,p-1】的最大值进行分析:先分析前半段的影响:(1)如果p点大于1-p-1的最大值的时候我们直接利用前缀和O(1)得到【1,p-1】有多少个桃子被摘掉,然后加上当前这个。(2)如果p点小于等于【1,p-1】的最大值,那么这个点依旧对前半段不造成影响,前半段的值等于【1,p-1】中被摘掉的桃子的数量,

接下来就是最难得后半段的讨论:

之前处理这里思路被卡了很久:(1)如果p点大于1-p-1的最大值

因为当前点变小了,对后面点造成的影响就是会摘掉一些原先不会被摘的桃子,那么怎么确定这些桃子的具体是那些呢? 实际上我们可以推出,这些多摘的桃子都是在1到当前坐标中只小于p的数,因为这些数是当p变小了才多出来的,那么他们在1到当前点肯定是只小于p点,那么我们把它加到前一维为p的vecvector数组里,至于怎么找到这些值,我们只要多维护一个第二大值就可以了,这些第二大值就是有可能会多摘的桃子。当p点为原先会被摘的桃子时我们对存在v[p]里的值进行二分找到比p值修改后大的那些值,也就是后半段新增的值,再加上原先就要摘得值。

(2) 如果小于等于的话,依旧不造成影响,直接去前缀和就好了

3,假设输入的点和原来的点值一样,直接前缀和取

这样一共是五种主要情况: 两种用二分O(logn),另外三种直接前缀和O(1),稍微计算便可知不会超时。最后跑了405ms,题目给了2000mS,算跑的很快的了, 就是实现有点复杂,应该还有更好的解法,不过比赛的时候没想那么多,直接暴力莽过去了,还好过了要不改代码要改到吐。。QAQ

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5+;
struct node{
int id,val;
};
vector<int>v[M];
int a[M],ans[M],maxx[M],b[M],arr[M]; int main()
{
int t,n,q,p,c;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i = ;i <= n;i ++){
scanf("%d",&a[i]);
}
node mx,mx1;
mx.val = ; mx1.val = ,mx.id = ,mx1.id = ;
int cnt = ,num = ;
maxx[] = ;
for(int i = ;i <= n;i ++){
if(mx.val < a[i]){
mx1.val = mx.val; mx1.id = mx.id;
mx.val = a[i]; mx.id = i; b[cnt++] = a[i];
num++;
}
else if(mx1.val < a[i]){
mx1.val = a[i]; mx1.id = i;
v[mx.id].push_back(a[i]);
}
maxx[i] = mx.val; ans[i] = num;
}
while(q--){
scanf("%d%d",&p,&c);
int sum = ;
if(c > a[p]){
if(c > maxx[p-]){
sum ++; sum += ans[p-];
int kk = upper_bound(b,b+cnt,c) - b;
if(kk != cnt) sum += cnt-kk;
}
else
sum = ans[n];
}
else if(c == a[p]) sum = ans[n];
else{
if(c > maxx[p-]) sum++,sum += ans[p-];
else sum += ans[p-];
if(a[p] == maxx[p]){
int kk = upper_bound(v[p].begin(),v[p].end(),c)-v[p].begin();
sum += v[p].size() - kk;
int kk1 = upper_bound(b,b+cnt,a[p]) - b;
if(kk1 != cnt) sum += cnt-kk1;
}
else
sum = ans[n];
}
printf("%d\n",sum);
}
for(int i = ;i <= n;i ++){
maxx[i] = ; ans[i] = ; v[i].clear();
}
for(int i = ;i <= cnt;i ++) b[i] = ;
}
return ;
}

hdu 6406 Taotao Picks Apples (2018 Multi-University Training Contest 8 1010)(二分,前缀和)的更多相关文章

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

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

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

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

  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 & FJUT3592 做完其他题后才能做的题(线段树)题解

    题意(FJUT翻译HDU): 钱陶陶家门前有一棵苹果树. 秋天来了,树上的n个苹果成熟了,淘淘会去采摘这些苹果. 到园子里摘苹果时,淘淘将这些苹果从第一个苹果扫到最后一个. 如果当前的苹果是第一个苹果 ...

  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. HDU 6141 - I am your Father! | 2017 Multi-University Training Contest 8

    思路来自 FXXL 最小树形图模板用kuangbin的 /* HDU 6141 - I am your Father! [ 最小树形图 ] | 2017 Multi-University Traini ...

随机推荐

  1. python 取值方法:截取字符串

    截取最后三位:aa=“TFR20171230001-1”cc=aa[-3]+aa[-2]+aa[-1] aa="1.36x36.8-ddr" bb=aa.split('x')[1] ...

  2. C#中byte[]类型转换为其它类型

    我们这里就举byte[]类型和long类型的转换,其它数据类型用BitConverter类以此类推: /// <summary> /// 字节数组转换为long类型 /// </su ...

  3. 【vue】chrome已安装Vue Devtools在控制台却无显示

    chrome已安装Vue Devtools在控制台却无显示的解决: 在点亮Vue Devtools图标后,控制台没有vue解读显示. 原因:脚手架配置NODE_ENV直接定义为了production版 ...

  4. GitHub Git 简单操作

    一.使用git更新GitHub 准备:本地已经安装好git 登录GitHub,选择好仓库,点击 Clone or download 拷贝地址 这里的地址为:https://github.com/edw ...

  5. Luogu4774 NOI2018 屠龙勇士 ExCRT

    传送门 原来NOI也会出裸题啊-- 用multiset求出对付每一个BOSS使用的武器威力\(ATK_i\),可以得到\(m\)个式子\(ATK_ix \equiv a_i \mod p_i\) 看起 ...

  6. [转]zookeeper-端口说明

    一.zookeeper有三个端口(可以修改) 1.2181 2.3888 3.2888 二.3个端口的作用 1.2181:对cline端提供服务 2.3888:选举leader使用 3.2888:集群 ...

  7. 面试3——java集合类总结(List)

    1.集合类 数组:可以存储对象,也可以存储基本数据类型,但是一次只能存储一种类型,且长度一定,不可改变. 集合:只能存储对象,长度可变,可以存储不同类型的对象.Java集合类主要有三种:set,lis ...

  8. Note: SE Class's Individual Project

    虽然第一个Project还有点小问题需要修改,但是大体已经差不多了,先把blog记在这里,算是开博第一篇吧! 1.项目预计的用时 本来看到这个题的时候想的并不多,但是看了老师的要求才觉得如此麻烦ORZ ...

  9. 《Linux内核设计与实现》读书笔记 4 进程调度

    第四章进程调度 进程调度程序可看做在可运行太进程之间分配有限的处理器时间资源的内核子系统.调度程序是多任务操作系统的基础.通过调度程序的合理调度,系统资源才能最大限度地发挥作用,多进程才会有并发执行的 ...

  10. 使用Eclipse可以方便的统计工程或文件的代码行数,

    使用Eclipse可以方便的统计工程或文件的代码行数,方法如下: 1.点击要统计的项目或许文件夹,在菜单栏点击Search,然后点击File... 2.选中正则表达式(Regular expressi ...