• 2019ICPC南京网络赛F Greedy Sequence


    题意:对于1<=i<=n每次找到(pos[i]-k,pos[i]+k)内不大于i的最大那个数,ans[i]=ans[mx]+1,若ans[mx]未知则递归处理ans[mx]

    PS:这个题比赛时写主席树k前驱没剪枝T了,然而实验室里的同学n^2过10w...自闭

    主席树k前驱:在[l,r]范围内找到比k小的最大值,本质是带剪枝的主席树树上dfs

    主要算法思想:当前区间[l,r]的sum(数字个数)为0则剪枝,l==r时,如果l<k说明l是k的前驱,否则说明不存在k的前驱,查找时,如果k<=m+1(m=(l+r)/2)或者右区间不存在数字(数字个数为0)时,返回递归求左区间的答案(注意为什么是m+1,因为当k<=m+1时,小于k的值必定只可能出现在左区间[l,m]中),否则查找右区间,当递归右区间有解,则必为最优解,直接返回这个解即可,当右区间无解,才继续递归左区间求解

    这样一系列剪枝以后,这个算法就可以跑的很快了!

    其实还有个想法就是二分第k大值去求,这个思路比较简单而且复杂度是O(nlogn^2),不知道会不会T,有时间了尝试补上

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5+5;
    struct Node
    {
        int l,r,sum;
    }node[N*40];//nlogn
    int cnt;
    int a[N],root[N];
    void Insert(int l,int r,int pre,int& now,int val)
    {
        node[++cnt]=node[pre];
        now=cnt;
        node[now].sum++;
        if(l==r)return;
        int m=(l+r)>>1;
        if(val<=m)Insert(l,m,node[pre].l,node[now].l,val);
        else Insert(m+1,r,node[pre].r,node[now].r,val);
    }
    int query(int L,int R,int l,int r,int k)
    {
        if(node[R].sum-node[L].sum==0)return -1;
        if(l==r)return l<k?l:-1;
        int m=(l+r)>>1;
        if(k<=m+1||node[node[R].r].sum-node[node[L].r].sum==0)return query(node[L].l,node[R].l,l,m,k);
        int t=query(node[L].r,node[R].r,m+1,r,k);
        if(t!=-1)return t;
        return query(node[L].l,node[R].l,l,m,k);
    }
    int n,k;
    int pos[N],dp[N];
    int solve(int i)
    {
        if(dp[i]!=-1)return dp[i];
        int l=max(1,pos[i]-k);
        int r=min(n,pos[i]+k);
        int res=query(root[l-1],root[r],1,n,i);
        if(res==-1)return dp[i]=1;
        return dp[i]=solve(res)+1;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        int T;
        cin>>T;
        while (T--) {
            cnt=0;
            memset(dp,-1, sizeof(dp));
            memset(node,0, sizeof(node));
            cin >> n >> k;
            for (int i = 1; i <= n; i++) {
                cin >> a[i];
                pos[a[i]]=i;
            }
            for (int i = 1; i <= n; i++) {
                Insert(1, n, root[i - 1], root[i], a[i]);
            }
            for(int i=1;i<=n;i++)
            {
                solve(i);
                cout<<dp[i]<<(i==n?'
    ':' ');
            }
        }
        return 0;
    }
  • 相关阅读:
    博科SAN交换机基本配置(华为SNS系列交换机为例OEM博科)
    华为SNS交换机(OEM博科FC交换机)Fabric OS: v 8版本后通过https方式浏览器访问交换机Webtools显示没有匹配的加密算法套件的解决办法
    SNS光纤交换机怎样禁用 Virtual Fabric模式
    光纤网络的相关知识
    元音老人:怎样了生死
    戒淫偈【每天念十遍】。。。
    戒淫偈汇集
    净空老法师:你能这样念上一个星期试试看,肯定比你过去念十年还有效!
    修华严奥旨妄尽还原观 第6集
    贤公和尚,佛门榜样。-海贤老和尚往生纪实
  • 原文地址:https://www.cnblogs.com/xusirui/p/11462666.html
Copyright © 2020-2023  润新知