zoukankan      html  css  js  c++  java
  • 防线 Defence

    这一题写的时候也是懵逼的,想到了大概思路

    首先的操作肯定是处理出以 ii 为结尾的最长连续上升序列

    那么接下来最朴素的算法可以达到 O(N^2)

    有没有更快的做法?

    考虑我们枚举的是前 ii 项,那么有些很明显无用的东西被重复枚举了

    如果 a[i]>a[j] 并且 g[i]<=g[j] ,那么选 i肯定没有选 j 优,所以考虑用一个

    set来维护这个东西,注意细节

    #include<bits/stdc++.h>
    using namespace std;
    set<pair<int,int> > q;
    int n,a[200005],h[200005],g[200005];
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
           scanf("%d",&n);g[n+1]=0;
           for(int i=1;i<=n;i++) scanf("%d",&a[i]);
           for(int i=1;i<=n;i++) h[i]=a[i]>a[i-1]?h[i-1]+1:1;//预处理
           for(int i=n;i>=1;i--) g[i]=a[i]<a[i+1]?g[i+1]+1:1;
           q.clear();
           int ans=1;q.insert(make_pair(a[1],h[1]));//用pair维护
           for(int i=2;i<=n;i++){
             pair<int,int> x(a[i],h[i]);
             set<pair<int,int> > :: iterator it=q.lower_bound(x);//找到满足条件的
             if(it!=q.begin()){
                --it;ans=max(ans,(*it).second+g[i]);//更新答案
                if((*it).second>=x.second)continue;//如果已经可以比i更优,直接跳过i
             }
             q.erase(x);q.insert(x);//抹去原本存在的x,重新插入,以便找到位置 
             it=++q.find(x);
             while(it!=q.end()){
              if((*it).second<=x.second&&(*it).first>x.first)q.erase(it);//找到合适的位置插入,并删除不可能的答案 
              else break;
              ++it;//往后迭代 
             }
             q.insert(x);//插入,再次更新 
           }
           printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    消息摘要技术(MD5)
    编写JsonResult封装JSON返回值(模板参阅)
    JS面向对象编程(进阶理解)
    markdown常用语法教程
    Spring-MVC请求参数值和向页面传值
    Spring-MVC开发步骤(入门配置)
    Live Templates快捷键模板
    压力测试中java.net.BindException: Address already in use: connect
    jmeter初始化工作
    xshell配色
  • 原文地址:https://www.cnblogs.com/coder-cjh/p/11622986.html
Copyright © 2011-2022 走看看