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;
    }
    
  • 相关阅读:
    7月的尾巴,你是XXX
    戏说Android view 工作流程《下》
    “燕子”
    Android开机动画bootanimation.zip
    戏说Android view 工作流程《上》
    ViewController里已连接的IBOutlet为什么会是nil
    My first App "Encrypt Wheel" is Ready to Download!
    iOS开发中角色Role所产生的悲剧(未完)
    UIScrollView实现不全屏分页的小技巧
    Apple misunderstood my app,now my app status changed to “In Review”
  • 原文地址:https://www.cnblogs.com/lhm-/p/13431140.html
Copyright © 2011-2022 走看看