[关闭]
@y20070316 2017-02-15T06:40:42.000000Z 字数 5348 阅读 930

GDKOI2017模拟赛二

OI 校内赛


【xsy1815】clear - 栈+kmp

题意

给你两个串,每次在串中从左到右找串,并将该子串删除,直到找不到为止,问你能删几次。

分析

肯定是从前往后跑,能合并的就合并。
快速判断能不能合并的方法有:
①栈+kmp
②栈+字符串Hash
③etc

个人觉得那种深度的冥想也可以在打OI的时候使用。
闭上眼睛好好地想想。
(什么玄学的东西qaq)

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  4. const int A=524288;
  5. const int B=10000010;
  6. char a[A];
  7. int na;
  8. int nx[A];
  9. char b[B];
  10. int nb;
  11. char c[B];
  12. int nc;
  13. int ex[B];
  14. int cnt;
  15. int main(void) {
  16. #ifndef ONLINE_JUDGE
  17. freopen("A.in","r",stdin);
  18. freopen("A.out","w",stdout);
  19. #endif
  20. scanf("%s",a+1);
  21. na=strlen(a+1);
  22. nx[1]=0;
  23. int j=0;
  24. F(i,2,na) {
  25. while (j>0&&a[i]!=a[j+1])
  26. j=nx[j];
  27. if (a[i]==a[j+1])
  28. j++;
  29. nx[i]=j;
  30. }
  31. scanf("%s",b+1);
  32. nb=strlen(b+1);
  33. F(i,1,nb) {
  34. int j=ex[nc];
  35. while (j>0&&b[i]!=a[j+1])
  36. j=nx[j];
  37. if (b[i]==a[j+1])
  38. j++;
  39. if (j==na) {
  40. cnt++;
  41. F(i,2,na)
  42. c[nc--]=0;
  43. }
  44. else {
  45. c[++nc]=b[i];
  46. ex[nc]=j;
  47. }
  48. }
  49. printf("%d\n",cnt);
  50. return 0;
  51. }

【xsy1820】mst - 最小割

题意

给定一个边带正权的连通无向图,其中个点从依次编号,
给定三个正整数,和,假设现在加入一条边权为的边,那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
数据保证原图为联通图。

分析

什么叫做出现在最小生成树或者最大生成树上。
最小生成树和最大生成树类似,考虑最小生成树。

可能出现,意味着对于任意一个经过的环,这条边都不是环上的最大值。
即:我们把当做起点,把当做终点,不存在一条路径,满足每一条边的长度都小于

我们考虑一张图,个点,把小于的边给实质化。
那么,现在要断掉一些小于的边,使得不连通。

最小割!
网络流。

如果既要求最小生成树又要求最大生成树呢?
注意到两个图的边没有交集。
所以最小生成树求一次最小割,最大生成树也求一次最小割就好了。

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cctype>
  4. #include <algorithm>
  5. using namespace std;
  6. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  7. #define fore(k,u) for (int k=hd[u];k>0;k=mp[k].nx)
  8. int rd(void);
  9. const int N=524288;
  10. const int INF=(0x7fffffff)>>1;
  11. int n,m;
  12. struct Ed {
  13. int u,v,l;
  14. Ed(int _u=0,int _v=0,int _l=0) {
  15. u=_u,v=_v,l=_l;
  16. }
  17. }ed[N];
  18. int u,v,l;
  19. struct G {
  20. int v,f,nx;
  21. G(int _v=0,int _f=0,int _nx=0) {
  22. v=_v,f=_f,nx=_nx;
  23. }
  24. }mp[N];
  25. int tot,hd[N];
  26. int q[N],qh,qt;
  27. int lev[N];
  28. int ans;
  29. void Ins(int u,int v,int f) {
  30. mp[++tot]=G(v,f,hd[u]);
  31. hd[u]=tot;
  32. mp[++tot]=G(u,f,hd[v]);
  33. hd[v]=tot;
  34. }
  35. void Build(int kd) {
  36. tot=1;
  37. memset(hd,0,sizeof hd);
  38. F(i,1,m)
  39. if (kd==(l<ed[i].l))
  40. Ins(ed[i].u,ed[i].v,1);
  41. }
  42. int BFS(int fs,int ft) {
  43. memset(q,0,sizeof q);
  44. qh=qt=0;
  45. memset(lev,0,sizeof lev);
  46. q[++qt]=fs;
  47. lev[fs]=1;
  48. while (qh!=qt) {
  49. int x=q[++qh];
  50. fore(k,x)
  51. if (mp[k].f>0&&!lev[mp[k].v]) {
  52. lev[mp[k].v]=lev[x]+1;
  53. if (mp[k].v==ft)
  54. return 1;
  55. q[++qt]=mp[k].v;
  56. }
  57. }
  58. return 0;
  59. }
  60. int DFS(int x,int ft,int flow) {
  61. if (x==ft)
  62. return flow;
  63. int sum=0;
  64. fore(k,x)
  65. if (mp[k].f>0&&lev[mp[k].v]==lev[x]+1) {
  66. int t=DFS(mp[k].v,ft,min(flow,mp[k].f));
  67. if (t>0) {
  68. sum+=t;
  69. flow-=t;
  70. mp[k].f-=t;
  71. mp[k^1].f+=t;
  72. if (!flow) break;
  73. }
  74. else lev[mp[k].v]=INF;
  75. }
  76. return sum;
  77. }
  78. int Dinic(void) {
  79. int mx_flow=0;
  80. while (1) {
  81. int tag=BFS(u,v);
  82. if (!tag)
  83. break;
  84. int del=DFS(u,v,INF);
  85. mx_flow+=del;
  86. }
  87. return mx_flow;
  88. }
  89. int main(void) {
  90. #ifndef ONLINE_JUDGE
  91. freopen("B.in","r",stdin);
  92. freopen("B.out","w",stdout);
  93. #endif
  94. n=rd(),m=rd();
  95. F(i,1,m) {
  96. int u=rd(),v=rd(),l=rd();
  97. ed[i]=Ed(u,v,l);
  98. }
  99. u=rd(),v=rd(),l=rd();
  100. Build(0);
  101. ans+=Dinic();
  102. Build(1);
  103. ans+=Dinic();
  104. printf("%d\n",ans);
  105. return 0;
  106. }
  107. int rd(void) {
  108. int x=0,f=1; char c=getchar();
  109. while (!isdigit(c)) {
  110. if (c=='-') f=-1;
  111. c=getchar();
  112. }
  113. while (isdigit(c)) {
  114. x=x*10+c-'0';
  115. c=getchar();
  116. }
  117. return x*f;
  118. }

【xsy1828】string - 后缀数组+二分

题意

给出个字符串,求出一个最长的串,使得这个串或者这个串的回文在所有个字符串中都出现。

分析

把所有字符串存到一个大的字符串里面。
注意这里的姿势。

  1. int n;
  2. int star[N],fini[N],slen[N];
  3. int own[L];
  4. char s[L];
  5. int len;

中间加若干的连字符。
把原串和反串都加进来。

求SA。
二分答案。

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cctype>
  4. #include <algorithm>
  5. using namespace std;
  6. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  7. #define D(i,a,b) for (int i=(a);i>=(b);i--)
  8. int rd(void);
  9. const int N=256;
  10. const int L=131072;
  11. int nT;
  12. int n;
  13. int star[N],fini[N],slen[N];
  14. int own[L];
  15. char s[L];
  16. int len;
  17. int sa[L],rk[L],ht[L];
  18. int sum[L],tsa[L],trk[L];
  19. int al,ar;
  20. int mid;
  21. int vis[N];
  22. int tot,ind;
  23. void Prework(void) {
  24. memset(sa,0,sizeof sa);
  25. memset(rk,0,sizeof rk);
  26. memset(ht,0,sizeof ht);
  27. memset(sum,0,sizeof sum);
  28. memset(tsa,0,sizeof tsa);
  29. memset(trk,0,sizeof trk);
  30. int lim=512,p;
  31. F(i,1,len)
  32. sum[rk[i]=s[i]]++;
  33. F(i,1,lim)
  34. sum[i]+=sum[i-1];
  35. D(i,len,1)
  36. sa[sum[rk[i]]--]=i;
  37. rk[sa[1]]=p=1;
  38. F(i,2,len) {
  39. if (s[sa[i]]!=s[sa[i-1]])
  40. p++;
  41. rk[sa[i]]=p;
  42. }
  43. lim=p;
  44. for (int j=1;lim!=len;j<<=1) {
  45. p=0;
  46. memset(tsa,0,sizeof tsa);
  47. F(i,len-j+1,len)
  48. tsa[++p]=i;
  49. F(i,1,len)
  50. if (sa[i]>j)
  51. tsa[++p]=sa[i]-j;
  52. memset(sum,0,sizeof sum);
  53. memmove(trk,rk,sizeof rk);
  54. F(i,1,len)
  55. sum[rk[i]=trk[tsa[i]]]++;
  56. F(i,1,lim)
  57. sum[i]+=sum[i-1];
  58. D(i,len,1)
  59. sa[sum[rk[i]]--]=tsa[i];
  60. rk[sa[1]]=p=1;
  61. F(i,2,len) {
  62. if (trk[sa[i]]!=trk[sa[i-1]]||trk[sa[i]+j]!=trk[sa[i-1]+j])
  63. p++;
  64. rk[sa[i]]=p;
  65. }
  66. lim=p;
  67. }
  68. p=0;
  69. F(i,1,len) {
  70. if (p>0)
  71. p--;
  72. while (s[i+p]==s[sa[rk[i]-1]+p])
  73. p++;
  74. ht[rk[i]]=p;
  75. }
  76. }
  77. int contain(int xl,int xr,int yl,int yr) {
  78. return yl<=xl&&xr<=yr;
  79. }
  80. void Add(int x,int lim) {
  81. int ow=own[x];
  82. if (!ow)
  83. return;
  84. if (vis[ow]==ind)
  85. return;
  86. int l=star[ow];
  87. int r=fini[ow];
  88. int mid=l+slen[ow];
  89. if (contain(x,x+lim-1,l,mid-1)||contain(x,x+lim-1,mid+1,r)) {
  90. vis[ow]=ind;
  91. tot++;
  92. }
  93. }
  94. int Check(int lim) {
  95. tot=ind=0;
  96. memset(vis,0,sizeof vis);
  97. F(l,1,len) {
  98. int r=l;
  99. while (r+1<=len&&ht[r+1]>=lim)
  100. r++;
  101. ind++,tot=0;
  102. F(i,l,r)
  103. Add(sa[i],lim);
  104. if (tot==n)
  105. return 1;
  106. l=r;
  107. }
  108. return 0;
  109. }
  110. int main(void) {
  111. #ifndef ONLINE_JUDGE
  112. freopen("C.in","r",stdin);
  113. freopen("C.out","w",stdout);
  114. #endif
  115. nT=rd();
  116. F(c,1,nT) {
  117. n=0;
  118. memset(star,0,sizeof star);
  119. memset(fini,0,sizeof fini);
  120. memset(slen,0,sizeof slen);
  121. memset(own,0,sizeof own);
  122. memset(s,0,sizeof s);
  123. len=0;
  124. n=rd();
  125. F(i,1,n) {
  126. int di=fini[i-1]+1;
  127. s[di]='>';
  128. star[i]=di+1;
  129. scanf("%s",s+di+1);
  130. slen[i]=strlen(s+di+1);
  131. s[di+slen[i]+1]='-';
  132. F(j,di+1,di+slen[i])
  133. s[2*(di+slen[i]+1)-j]=s[j];
  134. fini[i]=di+slen[i]+1+slen[i];
  135. F(j,star[i],fini[i])
  136. own[j]=i;
  137. }
  138. s[len=fini[n]+1]='>';
  139. Prework();
  140. al=0;
  141. ar=*max_element(slen+1,slen+n+1);
  142. while (al<ar) {
  143. mid=(al+ar+1)>>1;
  144. int tag=Check(mid);
  145. if (tag)
  146. al=mid;
  147. else ar=mid-1;
  148. }
  149. printf("%d\n",al);
  150. }
  151. return 0;
  152. }
  153. int rd(void) {
  154. int x=0,f=1; char c=getchar();
  155. while (!isdigit(c)) {
  156. if (c=='-') f=-1;
  157. c=getchar();
  158. }
  159. while (isdigit(c)) {
  160. x=x*10+c-'0';
  161. c=getchar();
  162. }
  163. return x*f;
  164. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注