您的位置:首页 > 其它

【Plan 第六场】【后缀数组模板】

2015-03-11 16:55 411 查看
题目见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
;
int n;
int sa
,he
,rk
,X
,Y
,c
;
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
;
int dp[2]
;
int mx[2][N*4];
int l
,r
,pos
,_pos
,ll
,rr
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: