【Plan 第六场】【后缀数组模板】
2015-03-11 16:55
411 查看
题目见2015-1 1.6
A
后缀数组乱搞,蒟蒻看到uoj有人DA胜过DC3,于是又换了个版。。。
B
直接贪心最小割
做过了,就没写代码= =
C
线段树+DP,很水辣
cena卡STL。。。还好窝3个点0.95s卡过去了~
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; }
相关文章推荐
- 模板 -- 后缀数组
- 后缀数组模板
- 后缀数组模板 by hzwer
- SA(后缀数组)——倍增法模板
- 后缀数组倍增算法模板详解
- 后缀数组 模板
- 后缀数组 模板
- 后缀数组【模板】
- 后缀数组 倍增法模板
- (模板)后缀数组(lcp和rmq)
- 【后缀数组】洛谷P3809模板题
- 【后缀数组】关于后缀数组模板的注解续
- POJ 1743 - Musical Theme 后缀数组模板+用后缀数组求不覆盖最长重复子序列
- cf244D. Match & Catch 字符串hash (模板)或 后缀数组。。。
- poj 2774 后缀数组模板
- UOJ.35.[模板]后缀排序(后缀数组 倍增)
- 后缀数组模板整理
- 【tyvj 1860】 后缀数组模板
- 后缀数组——附1(含模板)
- 后缀数组模板