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到当前点被摘掉的桃子的数量,然后我们枚举修改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+10;
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 = 1;i <= n;i ++){
            scanf("%d",&a[i]);
        }
        node mx,mx1;
        mx.val = 0; mx1.val = 0,mx.id = 0,mx1.id = 0;
        int cnt = 0,num = 0;
        maxx[0] = 0;
        for(int i = 1;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 = 0;
            if(c > a[p]){
                if(c > maxx[p-1]){
                sum ++;  sum += ans[p-1];
                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-1]) sum++,sum += ans[p-1];
                else sum += ans[p-1];
                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 = 0;i <= n;i ++){
            maxx[i] = 0; ans[i] = 0; v[i].clear();
        }
        for(int i = 0;i <= cnt;i ++)  b[i] = 0;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kls123/p/9483489.html

时间: 2024-10-14 22:05:46

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

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

Taotao Picks Apples Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2506    Accepted Submission(s): 786 Problem Description There is an apple tree in front of Taotao's house. When autumn comes

hdu6406 Taotao Picks Apples 多校第8场1010

Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n apples on the tree ripen, and Taotao will go to pick these apples. When Taotao picks apples, Taotao scans these apples from the first one to the last one. If

HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)

题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能)  第2为表示能不能构成2 ...  这样用d[1<<n] 的DP  像背包那样背 n次就可以 最后状态中第k位为1的就可以加上方法数. #include<cstring> #include<cstdio> #include<cmath> #include <

HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

题意:给定n*m个格子,每个格子能填0-k 的整数.然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案. 思路:网络流,一共 n+m+2个点   源点 到行连流量为 所给的 当前行之和.    每行 连到每一列 一条流量为  k的边,每列到汇点连 列和.如果流量等于总和则有解,反之无解(如果列总和不等于行总和也无解).  判断方案是否唯一 找残留网络是否存在长度大于2的环即可,有环说明不唯一. #include<cstdio> #include<cstring&

hdu 5792 World is Exploding(2016 Multi-University Training Contest 5——树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 643    Accepted Submission(s): 306 Problem Description Given a sequence A

hdu 5774 Where Amazing Happens(2016 Multi-University Training Contest 4——打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5774 Where Amazing Happens Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 443    Accepted Submission(s): 300 Problem Description As the premier m

【hdu 6406】Taotao Picks Apples

[链接] 我是链接,点我呀:) [题意] 题意相当于问你改变一个位置之后. 从左往右扫描最大值.这个最大值会改变多少次. [题解] 假设我们改变的是i这个位置,下面说的a[i]都是改成q之后的a[i] 我们完全可以直接暴力算出来左边的最大值会改变多少次以及右边的最大值会改变多少次. 那么如何找呢? 首先在1..i-1当中找到那个最大值a[idx1] 这个可以用st表预处理出来. 然后如果a[i]这个位置是更新最大值中的某一次的话ans++. 显然a[i]要满足>a[idx1] 如果不满足的话,那

hdu 6665 Calabash and Landlord (2019 Multi-University Training Contest 8 1009)(离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6665 题目大意:给定四个点分别为两个矩形的左上角和右下角,两个矩形与坐标轴平行,问坐标平面(含负轴,但矩形只在第一象限内,部分边可能在正轴上)被两个矩形划分为几个区域(原意问的是几个连通点集但因为是实数点所以相当于问的是区域). 思路:如题,离散化.可以看到点坐标的值可能非常大,但是注意求的只是区域个数,而并不用求每个区域内点的个数,所以我们想要的信息只有点和点之间的位置关系,这时候最简单的方法,就

2018 Nowcoder Multi-University Training Contest 2

Practice Link A. run 题意: 白云每次可以移动\(1\)米或者\(k\)米,询问移动的米数在\([L, R]\)范围内的方案数有多少. 思路: \(dp[i][2]\)表示到第\(i\)米,是通过\(1\)米的方式过来的还是\(k\)米的方式过来的,递推即可. 代码: #include <bits/stdc++.h> using namespace std; #define N 100010 const int p = 1e9 + 7; int f[N][2], g[N];