zoukankan      html  css  js  c++  java
  • 题解 洛谷 P4696 【[CEOI2011]Matching】

    题意即为在序列中找出给定排列能匹配相同的位置,这里的匹配相同指的是相对大小关系相同,即离散化后相同。

    因为是相对大小关系相同,所以只需考虑每个数所在的排名。可以对给定排列处理出 (num_i),为位置 (i) 之前小于位置 (i) 对应的数的个数,发现对于序列,(num_i) 相同,相对大小关系就相同。

    那么就只用考虑序列和给定排列 (num_i) 的匹配,这个可以通过 (KMP) 来实现,用树状数组来维护,匹配成功时在树状数组上加入贡献,失配时在树状数组上删去贡献。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 1000010
    #define lowbit(x) (x&(-x))
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,pos,cnt;
    int p[maxn],a[maxn],s[maxn],t[maxn],num[maxn],nxt[maxn],ans[maxn];
    void update(int x,int v)
    {
        while(x<=m) t[x]+=v,x+=lowbit(x);
    }
    int query(int x)
    {
        int v=0;
        while(x) v+=t[x],x-=lowbit(x);
        return v;
    }
    void clear()
    {
        pos=0;
        for(int i=1;i<=m;++i) t[i]=0;
    }
    int main()
    {
        read(n),read(m),num[n+1]=-1;
        for(int i=1;i<=n;++i)
        {
            int x;
            read(x),p[x]=i;
        }
        for(int i=1;i<=m;++i) read(a[i]),s[i]=a[i];
        sort(s+1,s+m+1);
        for(int i=1;i<=m;++i) a[i]=lower_bound(s+1,s+m+1,a[i])-s;
        for(int i=1;i<=n;++i) num[i]=query(p[i]),update(p[i],1);
        clear();
        for(int i=2;i<=n;++i)
        {
            while(pos&&query(p[i])!=num[pos+1])
            {
                for(int j=i-pos;j<i-nxt[pos];++j) update(p[j],-1);
                pos=nxt[pos];
            }
            if(query(p[i])==num[pos+1]) update(p[i],1),pos++;
            nxt[i]=pos;
        }
        clear();
        for(int i=1;i<=m;++i)
        {
            while(pos&&query(a[i])!=num[pos+1])
            {
                for(int j=i-pos;j<i-nxt[pos];++j) update(a[j],-1);
                pos=nxt[pos];
            }
            if(query(a[i])==num[pos+1]) update(a[i],1),pos++;
            if(pos==n) ans[++cnt]=i-n+1;
        }
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;++i) printf("%d ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    添加日志文件
    C库函数对文件的操作
    getpass的使用
    C语言实现 冒泡排序 选择排序 希尔排序
    批量Ping执行Bash脚本
    Script
    echo
    Centos7 pxe
    Rsync 参数
    Ip HostName查询
  • 原文地址:https://www.cnblogs.com/lhm-/p/13431140.html
Copyright © 2011-2022 走看看