• #1074 : 字体设计


    描述

    你正在协助某人开发某种新的 Linux 下的中文字体。

    现在需要给上图里的黄点做「位置锚固」,然而有些黄点的位置可以由「插值(IUP)」确定,这样就可以减少锚固的数量。

    例如,在上图中,#46 #49 #52 #53 的位置可以由 #42 和 #57 插值得到, 我就不需要去锚固它们,只需要固定 #42 和 #57 就可以了。 可以给这个字减少至少 12 字节 ……

    抽象一下问题,现在给出输入数组 a

    定义 ax 可以被 al 和 ar 插值得到为:

    存在 l < x < r

    使得 al ≤ ax ≤ ar 或者 al ≥ ax ≥ ar

    求最少的「锚固」元素的数目,使得非锚固元素都可以由其左右最靠近它的锚固元素插值得到。并输出锚固元素的下标。

    输入

    第一行输入一个数 n,表示数组的大小(1 ≤ n ≤ 105)。 接下来的一行,输入一行 n 个整数 a1, a2, ..., an,表示数组中的元素(1 ≤ ai ≤ 109)。所有 a互不相同。

    输出

    输出的第一行包含一个整数 ans,表示锚固元素的数目。 接下来一行包含 ans 个递增的整数,表示锚固元素的下标。

    提示

    额外的样例数据:

    样例输入 样例输出
    7
    1 2 3 10 5 6 4
    3
    1 4 7

    样例输入

    8
    3 4 2 1 8 5 7 6

    样例输出

    7
    1 2 4 5 6 7 8 


    首先左右端点是一定要选的,根据这个性质。所以我们可以用solve(l,r)表示处理[l,r]区间,且已经选了l和r。
    那么我们求出[l,r]的最小值和最大值的位置,如果其中一个位置不符合要求,肯定要选成锚固元素,递归处理即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int A[maxn],cnt,ans[maxn];
    int mx[maxn][20],mn[maxn][20],Log[maxn];
    void init(int n) {
        Log[0]=-1;
        rep(i,1,n) Log[i]=Log[i>>1]+1;
        rep(i,1,n) mx[i][0]=mn[i][0]=i;
        for(int j=1;(1<<j)<=n;j++) 
            for(int i=1;i+(1<<j)-1<=n;i++) {
                int v1=mx[i][j-1],v2=mx[i+(1<<j-1)][j-1];
                mx[i][j]=A[v1]>A[v2]?v1:v2;
                v1=mn[i][j-1],v2=mn[i+(1<<j-1)][j-1];
                mn[i][j]=A[v1]<A[v2]?v1:v2;
            }
    }
    void query(int l,int r,int& p1,int& p2) {
        int k=Log[r-l+1];
        p1=A[mx[l][k]]>A[mx[r-(1<<k)+1][k]]?mx[l][k]:mx[r-(1<<k)+1][k];
        p2=A[mn[l][k]]<A[mn[r-(1<<k)+1][k]]?mn[l][k]:mn[r-(1<<k)+1][k];
    }
    void solve(int l,int r) {
        if(l+1>=r) return;
        int p1,p2;query(l+1,r-1,p1,p2);
        if(A[p2]<min(A[l],A[r])) ans[++cnt]=p2,solve(l,p2),solve(p2,r);
        else if(A[p1]>max(A[l],A[r])) ans[++cnt]=p1,solve(l,p1),solve(p1,r);
    }
    int main() {
        int n=read();
        rep(i,1,n) A[i]=read();
        init(n);
        ans[++cnt]=1;ans[++cnt]=n;
        solve(1,n);
        printf("%d
    ",cnt);
        sort(ans+1,ans+cnt+1);
        printf("%d",ans[1]);rep(i,2,cnt) printf(" %d",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    python操作excel文件一(xlrd读取文件)
    pytest 1.简单介绍一,安装和如何运行
    request鉴权的处理和判断
    Struts2 easy UI插件
    Struts2 JQuery UI常用插件
    Struts2 JSON
    Struts2 使用jQuery实现Ajax
    Struts2 Ajax校验
    oracle连接方式、创建数据库用户、忘记数据库密码、用户锁定
    第二次考试:错题总结
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4802709.html
Copyright © 2020-2023  润新知