【Plan 第六場】【後綴數組模板】


題目見2015-1 1.6


A

後綴數組亂搞,蒟蒻看到uoj有人DA勝過DC3,於是又換了個版。。。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
#define pii pair<int,int>
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
////////////////////////////////////////////////
const int N=500010;
char s[N];
int n;
int sa[N],he[N],rk[N],X[N],Y[N],c[N];
pii mi[N*4];
////////////////////////////////////////////////
#define LS o<<1,L,mid
#define RS o<<1|1,mid+1,R
void build(int o,int L,int R)
{
	if(L==R)
	{
		mi[o]=make_pair(he[L],L);
		return;
	}
	int mid=L+R>>1;
	build(LS); build(RS);
	mi[o]=min(mi[o<<1],mi[o<<1|1]);
}
pii getmin(int l,int r,int o,int L,int R)
{
	if(l<=L && R<=r) return mi[o];
	int mid=L+R>>1;
	if(r<=mid) return getmin(l,r,LS);
	else if(l>mid) return getmin(l,r,RS);
	else return min(getmin(l,mid,LS),getmin(mid+1,r,RS));
}
void calheight()
{
	int i,j,k=0;
	for(i=1;i<=n;he[rk[i++]]=k)
	for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
}
void da(int m=26)
{
	#define cmp(u,v,k) (x[u]!=x[v]||x[u+k]!=x[v+k])
	int *x=X,*y=Y,*t,k,p;
	rep(i,1,n) c[x[i]=s[i]-'a'+1]++;
	rep(i,1,m) c[i]+=c[i-1];
	per(i,n,1) sa[c[x[i]]--]=i;
	for(k=1;k<n&&(k==1||m<n);k<<=1,t=x,x=y,y=t)
	{
		p=0;
		rep(i,n-k+1,n) y[++p]=i;
		rep(i,1,n) if(sa[i]>k) y[++p]=sa[i]-k;
		rep(i,1,m) c[i]=0;
		rep(i,1,n) c[x[i]]++;
		rep(i,1,m) c[i]+=c[i-1];
		per(i,n,1) sa[c[x[y[i]]]--]=y[i];
		m=0;
		rep(i,1,n) y[sa[i]]=i==1||cmp(sa[i],sa[i-1],k)?++m:m;
	}
	rep(i,1,n) rk[sa[i]]=i;
	calheight();
}
LL cal(int l,int r)
{
	if(l>=r) return 0;
	pii ret=getmin(l+1,r,1,1,n);
	LL res=0,mid=ret.second;
	res+=(LL)2*((mid-l)*(r-mid+1))*ret.first;
	res+=cal(l,mid-1);
	res+=cal(mid,r);
	return res;
}
////////////////////////////////////////////////
void input()
{
    scanf("%s",s+1);
    n=strlen(s+1);
}
void solve()
{
	da(); he[1]=n;
	//rep(i,1,n) printf("%d\n",he[i]);
	build(1,1,n);
	LL ans=0;
	rep(i,1,n) ans+=(LL)(n-1)*i;
	ans-=cal(1,n);
	cout<<ans<<endl;
}
////////////////////////////////////////////////
int main()
{
    freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    input(),solve();
    return 0;
}


B

直接貪心最小割

做過了,就沒寫代碼= =


C

線段樹+DP,很水辣

cena卡STL。。。還好窩3個點0.95s卡過去了~

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
////////////////////////////////////////////////
const int N=200010;
int n,k,a[N];
int dp[2][N];
int mx[2][N*4];
int l[N],r[N],pos[N],_pos[N],ll[N],rr[N];
multiset<pair<int,int> >S;
////////////////////////////////////////////////
#define LS o<<1,L,mid,mx
#define RS o<<1|1,mid+1,R,mx
void MAX(int &a,int b){if(a<b)a=b;}
void insert(int pos,int x,int o,int L,int R,int *mx)
{
	if(L==R)
	{
		MAX(mx[o],x);
		return;
	}
	int mid=L+R>>1;
	if(pos<=mid) insert(pos,x,LS);
	else insert(pos,x,RS);
	mx[o]=max(mx[o<<1],mx[o<<1|1]);
}
int getmax(int l,int r,int o,int L,int R,int *mx)
{
	if(r<1 || l>n) return 0;
	if(l<=L && R<=r) return mx[o];
	int mid=L+R>>1;
	if(r<=mid) return getmax(l,r,LS);
	else if(l>mid) return getmax(l,r,RS);
	else return max(getmax(l,mid,LS),getmax(mid+1,r,RS));
}
////////////////////////////////////////////////
void input()
{
	int cnt=0;
    n=read(); k=read();
    rep(i,1,n) a[i]=read(),S.insert(make_pair(a[i],i));
    for(multiset<pair<int,int> >::iterator it=S.begin();it!=S.end();it++)
        pos[++cnt]=it->second;
    sort(&a[1],&a[n+1]);
    rep(i,1,n) _pos[pos[i]]=i;
}
void solve()
{
	int cur=1;
	rep(i,1,n)
	{
		while(cur<n && a[cur+1]-a[i]<k) cur++;
		r[i]=cur;
	}
	cur=n;
	per(i,n,1)
	{
		while(cur>1 && a[i]-a[cur-1]<k) cur--;
		l[i]=cur;
	}
	cur=1;
	rep(i,1,n)
	{
		while(cur<n && a[cur+1]==a[i]) cur++;
		rr[i]=cur;
	}
	cur=n;
	per(i,n,1)
	{
		while(cur>1 && a[cur-1]==a[i]) cur--;
		ll[i]=cur;
	}
	int ans=0;
	rep(i,1,n)
	{
		dp[0][i]=getmax(1,l[_pos[i]]-1,1,1,n,mx[1])+1;
		dp[1][i]=getmax(r[_pos[i]]+1,n,1,1,n,mx[0])+1;
		if(dp[0][i]==1) dp[0][i]=0;
		insert(_pos[i],dp[0][i],1,1,n,mx[0]);
		insert(_pos[i],dp[1][i],1,1,n,mx[1]);
		MAX(ans,dp[0][i]);
		MAX(ans,dp[1][i]);
		//printf("dp[%d][%d]=%d\n",0,i,dp[0][i]);
		//printf("dp[%d][%d]=%d\n",1,i,dp[1][i]);
	}
	printf("%d\n",ans);
}
////////////////////////////////////////////////
int main()
{
    freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    input(),solve();
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章