• hdu-6406 线段树+二分


      这个题我觉得题意给你很明显了,就是让你判断这一个改变之后如何让前面和后面接上,熟悉的朋友很容易感觉出这个经典问题,最大值不断变化的值要是在一个数轴上画图像的话,是一个阶梯的形状,所以这个点抬高或降低就有很直观的影响了。

      1.对于这个点被降低:如果这个点不在阶梯的转角上,那么这个点没有任何意义,答案不变,如果在转角上,你要判断这个点下降后前面的最大值现在是多少(设为t),对后续产生了多少的影响,你现在要知道这个点之后的第一个大于t的值在哪即可接的上。

      2.对于这个点被抬高:如果这个点不在阶梯的转角上,还是像后查询第一个大于它的位置就行了,如果这个点不在转角上,但是有突破了阶梯的可能,这个时候前缀的最大值还是变了,查询第一和大于新最大值的位置同理。

      现在还要做的事情有两件:计算从i开始选能选的数量,如何在1p+1~n中查询第一个大于t的位置。

      第一个问题:其实你是可以从后往前维护一个单调栈即可,往里压的时候必须是降序即可。(具体看代码理解比较好一点)

      第二个问题:用线段树维护区间最大值,然后二分就行了。

      总结:这道题思路来的很快,先是乱写了两发,根本情况想的非常天真,我太蠢了,乱交。后来预处理后缀居然写了一个线段树+离散的,明明如此复杂,能解决这个问题的方法不止一种,那么我为什么选了一个如此复杂的狗东西呢,下次多想一想不行吗?还有代码出现了bug,不知道是不是状态问题,一个小细节错了,查了好久。最后一个大傻逼bug是我没有计算上什么都没有这种情况的后缀,真是太傻了,思路还是不严谨。

      期望更改方案:正常估计比较难的题多想一想,别脑子一热就写(感觉cf打多,上来一顿胡猜,但是难题别自以为是啊),方法太复杂的时候别觉得自己就是对了,多动脑想一想其他的会死人?还有下次查错,全方位的分析可能发生的所有情况!!!

      

    #include<iostream>
    #include<cstring>
    #include <string>
    #include<algorithm>
    #include<map>
    #include<stack>
    #define lson rt<<1
    #define rson rt<<1|1
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+20;
    int tree[maxn*4];
    void insert(int x,int p,int l,int r,int rt)
    {
        if(l==x&&r==x)
        {
            tree[rt]=p;
            return;
        }
        int mid=(l+r)/2;
        if(x<=mid)
            insert(x,p, l, mid, lson);
        else
            insert(x,p, mid+1, r, rson);
        tree[rt]=max(tree[lson],tree[rson]);
    }
    int qu(int L,int R,int l,int r,int rt)
    {
       if(L<=l&&r<=R)
       {
           return tree[rt];
       }
       else
       {
           int mid=(l+r)/2;
           int ans=0;
           if(L<=mid)
               ans=max(ans,qu(L, R, l, mid, lson));
           if(R>mid)
               ans=max(ans,qu(L, R, mid+1, r, rson));
           return ans;
       }
    }
    int ans[maxn],ans_pre[maxn],a[maxn],h[maxn],n,m;
    map<int ,int> M;
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%d%d",&n,&m);
            
            for(int i=1;i<=n;i++){
                scanf("%d",&h[i]);
            }
            
            
            
            for(int i=0;i<=4*maxn;i++)
                tree[i]=0;
            
            for(int i=1;i<=n;i++)
                insert(i, h[i], 1, n, 1);
            stack<int> S;
            for(int i=n;i>0;i--)
            {
                while(1){
                if(S.empty()||S.top()>h[i]){
                    S.push(h[i]);
                    ans[i]=S.size();
                    break;
                }
                else
                    S.pop();
                }
            }
            
            a[1]=h[1];
            ans_pre[1]=1;
            for(int i=2,j=h[1];i<=n;i++)
            {
                if(h[i]>j)
                {
                    ans_pre[i]=ans_pre[i-1]+1;
                    j=h[i];
                    a[i]=h[i];
                }
                else
                {
                    a[i]=a[i-1];
                    ans_pre[i]=ans_pre[i-1];
                }
            }
            
            for(int i=0;i<m;i++)
            {
                int p,q;
                scanf("%d%d",&p,&q);
                
                int ans1=ans_pre[p];
                if(a[p]<q)
                {
                    if(p!=1&&a[p]==a[p-1])
                        ans1++;
                    
                    int l=p+1,r=n;
                    if(l<=r&&qu(p+1, n, 1, n, 1)>q){
                        while(r>l+1)
                        {
                            int mid=(l+r)/2;
                            if(qu(l, mid, 1, n, 1)>q)
                                r=mid;
                            else
                                l=mid;
                        }
                        if(h[l]<=q)
                            l=r;
                        ans1+=ans[l];
                    }
                }
                else if(p==1)
                {
                    int l=p+1,r=n;
                    if(l<=r&&qu(p+1, n, 1, n, 1)>q){
                        while(r>l+1)
                        {
                            int mid=(l+r)/2;
                            if(qu(l, mid, 1, n, 1)>q)
                                r=mid;
                            else
                                l=mid;
                        }
                        if(h[l]<=q)
                            l=r;
                        ans1+=ans[l];
                    }
                    
                }
                else if(a[p]!=a[p-1])
                {
                    if(q<=a[p-1]){
                        ans1--;
                        q=a[p-1];
                    }
                    
                    int l=p+1,r=n;
                    if(l<=r&&qu(p+1, n, 1, n, 1)>q){
                        while(r>l+1)
                        {
                            int mid=(l+r)/2;
                            if(qu(l, mid, 1, n, 1)>q)
                                r=mid;
                            else
                                l=mid;
                        }
                        if(h[l]<=q)
                            l=r;
                        ans1+=ans[l];
                    }
                }
                else
                    ans1=ans_pre[n];
                printf("%d
    ",ans1);
            }
        }
    }
  • 相关阅读:
    Windows Power Shell
    一个自律的人有多可怕!
    Android之TextureView浅析
    BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第9章节--client对象模型和REST APIs概览 介绍SP2013中远程APIs
    敌兵布阵(线段树)
    kendo AutoComplete实现多筛选条件
    Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法
    让我心碎的五道题
    输入一列数组,输出它的逆序数组
    centos下配置防火墙port失败
  • 原文地址:https://www.cnblogs.com/King-of-Dark/p/11616403.html
Copyright © 2020-2023  润新知