zoukankan      html  css  js  c++  java
  • 【SDOI2008】Sandy的卡片(二分答案+后缀数组)

    【SDOI2008】Sandy的卡片

    SA 经典题型:后缀数组+二分答案。

    本题不难,我们需要先要处理题目重新定义的这个“相等”。这个处理方式和一道 HDU 的题很像,好像叫 Musical Theme。我们只需要记录数组相邻两个数字的变化量即可。因为在数字加上同一个数后,差是不变的。

    我们把每个处理后的数组拼接到一起,求一遍后缀数组,我们需要的是二分答案 \(x\),只要有连续的 height 大于 \(x\),且每个字符串都出现过,就返回 true

    有个细节需要注意一下的。传统的两个字符串拼接中间要加一个 $,放置两个串互相影响。而这里是 \(n\) 个字符串拼接,我们为了区别,我们需要加 \(1\)$\(2\) 个,\(3\) 个……,以此类推,防止 1 0 -1 $ 1 -1 $ 1 这种情况的出现。

    //Don't act like a loser.
    //This code is written by huayucaiji
    //You can only use the code for studying or finding mistakes
    //Or,you'll be punished by Sakyamuni!!!
    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    
    int read() {
    	char ch=getchar();
    	int f=1,x=0;
    	while(ch<'0'||ch>'9') {
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') {
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return f*x;
    }
    
    const int MAXN=1e6+10; 
    
    int n,m,len;
    int sa[MAXN],rnk[MAXN],height[MAXN],w[101],num[MAXN],s[MAXN],bel[MAXN];
    
    struct pr {
    	int x,y,id;
    	bool operator <(const pr b)const {
    		if(x!=b.x) {
    			return x<b.x;
    		}
    		return y<b.y;
    	}
    }p[MAXN];
    
    void get_sa() {
    	for(int i=1;i<=len;i++) {
    		rnk[i]=s[i];
    	}
    	for(int l=1;l<len;l<<=1) {
    		for(int i=1;i<=len;i++) {
    			p[i].x=rnk[i];
    			p[i].y=(i+l<=len? rnk[i+l]:0);
    			p[i].id=i;
    		}
    		sort(p+1,p+len+1);
    		
    		int t=0;
    		for(int i=1;i<=len;i++) {
    			if(p[i].x!=p[i-1].x||p[i].y!=p[i-1].y) {
    				t++;
    			}
    			rnk[p[i].id]=t;
    		}
    	}
    	
    	for(int i=1;i<=len;i++) {
    		sa[rnk[i]]=i;
    	}
    }
    void get_height() {
    	int h=0;
    	for(int i=1;i<=len;i++) {
    		if(h) {
    			h--;
    		}
    		if(rnk[i]==1) {
    			continue;
    		}
    		
    		int p=i+h;
    		int q=sa[rnk[i]-1]+h;
    		
    		while(p<=len&&q<=len&&s[p]==s[q]) {
    			p++;
    			q++;
    			h++;
    		}
    		height[rnk[i]]=h;
    	}
    }
    
    bool check(int x) {
    	set<int> s;
    	s.insert(bel[sa[1]]);
    	for(int i=2;i<=len;i++) {
    		if(height[i]>=x) {
    			s.insert(bel[sa[i]]);
    		}
    		else {
    			s.clear();
    			s.insert(bel[sa[i]]);
    		}
    		if(s.size()==n) {
    			return 1;
    		}
    	}
    	return 0;
    }
    
    signed main() {
    	int l=0,r=1e9+10;
    	cin>>n;
    	for(int i=1;i<=n;i++) {
    		m=read();
    		r=min(r,m);
    		for(int j=1;j<=m;j++) {
    			w[j]=read();
    			if(j>1) {
    				s[++len]=w[j]-w[j-1];
    				bel[len]=i;
    			}
    		}
    		if(i!=n) {
    			for(int j=1;j<=i;j++) {
    				s[++len]=1e9;
    			}
    		}
    	}
    	
    	get_sa();
    	get_height();
    	
    	while(l+1<r) {
    		int mid=(l+r)>>1;
    		if(check(mid)) {
    			l=mid;
    		}
    		else {
    			r=mid;
    		}
    	}
    	if(check(r)) {
    		cout<<r+1<<endl;
    	}
    	else {
    		cout<<l+1<<endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Linux下的vim简易配置与Windows下的vim配置
    ASP.NET MVC2(Visual Studio.NET 2010)学习之路(一)
    NonSQL
    完成公司核名
    调试iOS 已经发布代码 Crash 文件分析出出错对应代码
    iOS RSA公钥加密数据 服务端接受PHP私钥解密 反过服务端公钥加密数据 iOS端私钥解密数据
    iOS 日期格式串 setDateFormat 显示格式代码
    iOS5 UI 设计新手段 Storyboard
    UIEdgeInsets
    xcode调试找出错误行
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/LG2463.html
Copyright © 2011-2022 走看看