題目見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;
}