• Matching「CEOI2011」


    题意

    对于整数序列 ((a_1,a_2,cdots,a_n))(1sim n)的排列((p_1,p_2,cdots,p_n)),称 ((a_1,a_2,cdots,a_n))符合 ((p_1,p_2,cdots,p_n)),当且仅当:

    • ({a})中任意两个数字互不相同;
    • ((a_1,a_2,cdots,a_n))从小到大排序后,将会得到 ((a_{p_1},a_{p_2},cdots,a_{p_n}))

    现在给出 (1sim n) 的排列 ({p}) 和序列 (h_1,h_2,cdots,h_m),请你求出哪些 ({h}) 的子串符合排列({p})


    思路

    可以想到,两个数组排列顺序一致,意味着对于每一个数,它前面比它小的数数量相等。

    于是我们可以预处理出这个“顺序对”数组,然后kmp转移。

    由于每一次跳区间的时候都会删一些数加一些数,所以使用树状数组进行动态维护。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO {
    
    	template<typename T>inline void read (T &x) {
    		x=0;T f=1;char c=getchar();
    		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
    		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write (T x) {
    		if (x<0) putchar('-'),x*=-1;
    		if (x>=10) write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Project {
    	
    	const int N=1000100;
    	
    	int n,m;
    	int p[N],rnk[N],h[N],b[N],v[N];
    	int nxt[N];
    	int tot,ans[N];
    	int tree[N];
    	
    	#define lowbit(x) x&(-x)
    	inline void update (int x,int v) {
    		for (register int i=x; i<=m; i+=lowbit(i)) tree[i]+=v;
    	}
    	inline int query (int x) {
    		int res=0;
    		for (register int i=x; i; i-=lowbit(i)) res+=tree[i];
    		return res;
    	}
    	
    	inline void MAIN () {
    		read(n),read(m);
    		for (register int i=1; i<=n; ++i) {
    			read(p[i]),rnk[p[i]]=i;
    		}
    		for (register int i=1; i<=m; ++i) {
    			read(h[i]),b[i]=h[i];
    		}
    		sort(b+1,b+m+1);
    		for (register int i=1; i<=m; ++i) 
    			h[i]=lower_bound(b+1,b+m+1,h[i])-b;
    		for (register int i=1; i<=n; ++i) v[i]=query(rnk[i]),update(rnk[i],1);
    		
    		
    		memset(tree,0,sizeof(tree));
    		for (register int i=2,j=0; i<=n; ++i) {
    			while (j>0&&query(rnk[i])!=v[j+1]) {
    				for (register int k=i-j; k<i-nxt[j]; ++k) 
    					update(rnk[k],-1);
    				j=nxt[j];
    			}
    			if (query(rnk[i])==v[j+1]) ++j;
    			nxt[i]=j;
    			update(rnk[i],1);
    		}
    		
    		
    		
    		
    		memset(tree,0,sizeof(tree));
    		for (register int i=1,j=0; i<=m; ++i) {
    			while (j==n||(j>0&&query(h[i])!=v[j+1])) {
    				for (register int k=i-j; k<i-nxt[j]; ++k) 
    					update(h[k],-1);
    				j=nxt[j];
    			} 
    			if (query(h[i])==v[j+1]) ++j;
    			update(h[i],1);
    			if (j==n) ans[++tot]=i-n+1;
    		}
    		
    		
    		
    		
    		write(tot),puts("");
    		for (register int i=1; i<=tot; ++i) {
    			write(ans[i]),putchar(' ');
    		}
    	}
    	
    }
    
    int main () {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
  • 相关阅读:
    面向对象之继承
    面向对象之封装
    面向对象编程
    Centos7.7镜像源配置
    Centos7环境配置
    多表查询v1
    多表查询
    库相关操作
    数据库初识
    数据相关操作
  • 原文地址:https://www.cnblogs.com/ilverene/p/11785474.html
Copyright © 2020-2023  润新知