AtCoder Regular Contest 097


C - K-th Substring

题意:

求一个长度小于等于5000的字符串的第K小子串,相同子串算一个。

K<=5。

分析:

一眼看上去可能不是特别好做,但是因为\(k\le5\),所以确实没啥难度了。把每个字符为首的前五个子串放进去,然后排个序直接找就行了,复杂度\(O(5*n*\log_2{5n})\)。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <string>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <algorithm>
  7. #include <map>
  8. #define re register
  9. #define max(a,b) ((a)>(b)?(a):(b))
  10. #define min(a,b) ((a)<(b)?(a):(b))
  11. using namespace std;
  12. typedef long long ll;
  13. typedef unsigned long long ull;
  14. #define ms(arr) memset(arr, 0, sizeof(arr))
  15. const int inf = 0x3f3f3f3f;
  16. string s,t,ch[101];
  17. map<string,int> b;
  18. char minn;
  19. int l,num,k,flag,o;
  20. int main() {
  21. cin>>s;
  22. cin>>k;
  23. l=s.length();
  24. minn='{';
  25. for(re int i=0;i<l-5;i++){
  26. if(s[i]<minn){
  27. minn=s[i];
  28. o=i;
  29. }
  30. }
  31. ch[0]=" ";
  32. for(re int i=o; i<l; i++) {
  33. for(re int j=i; j<min(i+k,l); j++) {
  34. t+=s[j];
  35. if(b[t]==1) continue;
  36. b[t]=1;
  37. if(num!=0) {
  38. if(num<k) {
  39. for(re int h=num; h>=0; h--) {
  40. if(t>ch[h]) {
  41. ch[h+1]=t; break;
  42. }
  43. else {
  44. ch[h+1]=ch[h];
  45. }
  46. }
  47. num++;
  48. } else {
  49. for(re int h=num; h>=0; h--) {
  50. if(t>ch[h]) {
  51. ch[h+1]=t;
  52. flag=h;
  53. break;
  54. } else {
  55. ch[h+1]=ch[h];
  56. }
  57. }
  58. if(flag==num) {
  59. flag=0;
  60. break;
  61. }
  62. }
  63. } else
  64. ch[++num]=t;
  65. }
  66. t="";
  67. }
  68. cout<<ch[k];
  69. }

D - Equals

题意:

给出一个n的排列,m个(x,y)的数对,你可以交换序列中位于x,y的数字。

可以进行若干次交换,问最多有多少个\(a_i=i\)。

分析:

明显可以发现,一个联通块里的数字是可以任意交换的,所以并查集维护一下,\(O(n)\)即可求解。

  1. #include <iostream>
  2. #include <cmath>
  3. #include <string>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <algorithm>
  7. #define re register
  8. #define max(a,b) ((a)>(b)?(a):(b))
  9. #define min(a,b) ((a)<(b)?(a):(b))
  10. using namespace std;
  11. typedef long long ll;
  12. typedef unsigned long long ull;
  13. #define ms(arr) memset(arr, 0, sizeof(arr))
  14. const int inf = 0x3f3f3f3f;
  15. int f[1000001],r1,r2,a[100001],b[100001],ans;
  16. inline int read()
  17. {
  18. int x=0,c=1;
  19. char ch=' ';
  20. while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
  21. while(ch=='-') c*=-1,ch=getchar();
  22. while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
  23. return x*c;
  24. }
  25. int find(int x)
  26. {
  27. if(f[x]!=x) f[x]=find(f[x]);
  28. return f[x];
  29. }
  30. int main()
  31. {
  32. int n,m;
  33. n=read();m=read();
  34. for(re int i=1;i<=n;i++)
  35. a[i]=read(),b[a[i]]=i;
  36. for(re int i=1;i<=n;i++)
  37. f[i]=i;
  38. for(re int i=1;i<=m;i++){
  39. int x=read(),y=read();
  40. r1=find(a[x]);r2=find(a[y]);
  41. if(r1!=r2) f[r2]=r1;
  42. }
  43. for(re int i=1;i<=n;i++){
  44. r1=find(i),r2=find(a[i]);
  45. if(r1==r2)
  46. ans++;
  47. }
  48. cout<<ans;
  49. return 0;
  50. }

E - Sorted and Sorted

题意:

有n个黑球和n个白球的乱序排列,它们的编号都是1~n。

可以交换相邻的两个球,要使这两种颜色的球编号均为1~n递增排列,求最少的交换次数。

分析:

首先我们可以简单的思考,如果只有一种颜色,就是一逆序对裸题。那么两种颜色的球我们应该怎么办呢?

可以进行DP。

我们用\(f[i][j]\)表示已经放了编号为前i的白球和编号为前j的黑球,那么我们可以得到转移:

\(f[i+1][j]=f[i][j]+(第i+1号白球前大于i+1的白球的个数)+(大于j的黑球的个数)\)

\(f[i][j+1]\)同理。

于是我们可以\(n^2\)预处理每个球前面的编号大于j的黑\白球的个数。

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <string>
  5. #include <cstring>
  6. #include <cstdio>
  7. #include <algorithm>
  8. #include <queue>
  9. #include <set>
  10. #include <map>
  11. #define re register
  12. #define max(a,b) ((a)>(b)?(a):(b))
  13. #define min(a,b) ((a)<(b)?(a):(b))
  14. #define MAXN 4000007
  15. #define mo 19930726
  16. using namespace std;
  17. typedef unsigned long long ull;
  18. #define ms(arr) memset(arr, 0, sizeof(arr))
  19. const int inf = 0x3f3f3f3f;
  20. inline int read()
  21. {
  22. int x=0,c=1;
  23. char ch=' ';
  24. while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
  25. while(ch=='-')c*=-1,ch=getchar();
  26. while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
  27. return x*c;
  28. }
  29. int n,m,a[4001],f[2005][2005],cw[4001][2002],cb[4002][2001],pos[2][2001],col[4001];
  30. char s[2];
  31. int main()
  32. {
  33. n=read();
  34. for(re int i=1;i<=n<<1;i++){
  35. scanf("%s",s); a[i]=read();
  36. col[i]=(s[0]=='B');
  37. pos[col[i]][a[i]]=i;
  38. }
  39. memset(f,100,sizeof(f));
  40. f[0][0]=0;
  41. for(re int i=1;i<=n<<1;i++)
  42. for(re int j=0;j<=n;j++){
  43. cw[i][j]=cw[i-1][j];
  44. cb[i][j]=cb[i-1][j];
  45. if(a[i-1]>j) col[i-1]?cb[i][j]++:cw[i][j]++;
  46. }
  47. for(re int i=0;i<=n;i++){
  48. for(re int j=0;j<=n;j++){
  49. int x=pos[0][i+1],y=pos[1][j+1];
  50. f[i+1][j]=min(f[i+1][j],f[i][j]+cw[x][i+1]+cb[x][j]);
  51. f[i][j+1]=min(f[i][j+1],f[i][j]+cw[y][i]+cb[y][j+1]);
  52. }
  53. }
  54. cout<<f[n][n];
  55. }

F - Monochrome Cat

题意:

有一棵树,我们已知每个节点的颜色,现在可以任选一个起点开始,每一秒钟有两种选择:

1:选择一个与之相邻的节点并移动过去,同时翻转目标节点的颜色。

2:翻转当前所在节点的颜色。

问将整棵树都染成黑色所需要的最短时间是多少。

分析:

这道题真的不错。

首先我们可以确定这样一个点,如果某节点的某子树是全黑的,那么它就不会被遍历到,所以我们可以直接去掉这棵子树。

删掉所有这样的子树之后,我们就拥有了一棵所有叶子节点都是白色的树。

通过题意我们可以知道,我们必须完全的遍历这棵已经删过点的树。

然后我们先考虑一种简单的情况,就是我们起点和终点重合。那么我们每条边都要走两遍,也就是说我们只要找一个白点当起点,无论从哪一个白点开始都是一样的。

然后,我们又可以发现每个点经过的次数就是它的度数,这样我们可以直接凭空算出哪些点需要在原地停留一秒。

接下来我们思考起点不和终点重合

那么明显的一点就是,从起点到终点的路径中,每条边只走了一遍,那么我们可以知道,这条路径中原来需要等待一秒使其翻转的点都不用了,原来不用翻转的现在需要翻转了。

这样这个题就变成了我们给出一个由0和1构成的树,现在从中找出一条路径,最大化点数+路径上1的个数-0的个数。

这样我们就可以进行DP。

设f[i]表示i到叶子的最大和,g[i]表示i到叶子的父亲的最大和(叶子是终点)。

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <algorithm>
  7. #include <queue>
  8. #define re register
  9. #define max(a,b) ((a)>(b)?(a):(b))
  10. #define min(a,b) ((a)<(b)?(a):(b))
  11. #define MAXN 200007
  12. #define mo 19930726
  13. using namespace std;
  14. typedef unsigned long long ull;
  15. #define ms(arr) memset(arr, 0, sizeof(arr))
  16. const int inf = 0x3f3f3f3f;
  17. int head[MAXN],a[MAXN],c[MAXN],num,size[MAXN],f[MAXN],g[MAXN],si[MAXN],d[MAXN],ans,n;
  18. char s[MAXN];
  19. struct po
  20. {
  21. int nxt,to;
  22. }edge[MAXN];
  23. inline int read()
  24. {
  25. int x=0,c=1;
  26. char ch=' ';
  27. while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
  28. while(ch=='-')c*=-1,ch=getchar();
  29. while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
  30. return x*c;
  31. }
  32. inline void add_edge(int from,int to)
  33. {
  34. edge[++num].nxt=head[from];
  35. edge[num].to=to;
  36. head[from]=num;
  37. }
  38. void dfs(int u,int fa)
  39. {
  40. size[u]=1;si[u]=c[u];
  41. for(int i=head[u];i;i=edge[i].nxt){
  42. int v=edge[i].to;
  43. if(v!=fa){
  44. dfs(v,u);
  45. size[u]+=size[v];si[u]+=si[v];
  46. if(si[v]!=size[v]) d[v]++,d[u]++;
  47. }
  48. }
  49. }
  50. void dfs2(int u,int fa)
  51. {
  52. int max1=0,max2=0;
  53. if(d[u]==1&&fa){f[u]=a[u],g[u]=-1<<30;return;}
  54. for(int i=head[u];i;i=edge[i].nxt){
  55. int v=edge[i].to;
  56. if(v!=fa&&size[v]!=si[v]){
  57. dfs2(v,u);
  58. ans=max(ans,f[v]+max2+a[u]);
  59. ans=max(ans,g[v]+max1+a[u]);
  60. max1=max(max1,f[v]);
  61. max2=max(max2,g[v]);
  62. }
  63. }
  64. f[u]=max1+a[u];g[u]=max2+a[u];
  65. }
  66. int main()
  67. {
  68. n=read();
  69. for(re int i=1;i<=n-1;i++){
  70. int x=read(),y=read();
  71. add_edge(x,y);add_edge(y,x);
  72. }
  73. scanf("%s",s+1);
  74. int root=0;
  75. for(re int i=1;i<=n;i++){
  76. if(s[i]=='B') c[i]=1;
  77. else root=i;
  78. }
  79. if(root) dfs(root,0);
  80. else {
  81. cout<<"0";
  82. return 0;
  83. }
  84. int sum=0;
  85. for(int i=1;i<=n;i++){
  86. if(size[i]==si[i]) continue;
  87. sum+=d[i];
  88. if((d[i]+c[i])%2==0) sum++,a[i]=2;
  89. }
  90. dfs2(root,0);
  91. cout<<sum-ans;
  92. }

AtCoder Regular Contest 097的更多相关文章

  1. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  2. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  3. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  4. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  5. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

  6. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  7. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  8. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

  9. AtCoder Regular Contest 098

    AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定 ...

随机推荐

  1. [MongoDB]学习笔记--基本操作

    读取 db.collection.find() db.users.find( { age: {$gt: }}, {name: , address: } ).limit().sort({age:1}) ...

  2. src与href的异同

    相同点: 在跨域中,src,href,这些发送的请求都是get请求: 不同点: 1, 概念:href (Hypertext Reference)指定网络资源的位置: 理解:href 用作 " ...

  3. 【BZOJ3876】[Ahoi2014]支线剧情 有上下界费用流

    [BZOJ3876][Ahoi2014]支线剧情 Description [故事背景] 宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等.不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩 ...

  4. InetAddress类和InetSocketAddress的使用

    一简介 InetAddress是Java对IP地址的封装,代表互联网协议(IP)地址:InetAddress对象的获取只能通过静态方法,比如根据主机名获取主机的ip地址封装对象: ? 1 InetAd ...

  5. Less-mixin判断(守卫)二

    mixin卫士--判断 或与且语法 且:()and() 或:(),() --且 examlpe: .test(@a) when (isNumber(@a)) and (@a>=5){ font- ...

  6. 烂笔头-Spring3

    1.spring相关jar包的导入 2.配置文件bean.xml <?xml version="1.0" encoding="UTF-8"?> &l ...

  7. pt-online-schema-change线上DDL注意事项

    在使用pt-online-schema-change做线上DDL的时候对于数据量比较小的表问题不大,但是对于数据量比较大的表(比如:单表2亿数据)访问量较大的时候就有可能出现异常, 原本使用pt-on ...

  8. 数据库操作(使用FMDB)

    iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便.于是,就出现了一系列将SQLite API进行封装的库,例如FMDB.PlausibleDatabase.sqlitepers ...

  9. android问题总结

    1.当打开eclipse时出现如下窗口(内容如下) Error when loading the SDK: Error: Error parsing \Android\adt-bundle-windo ...

  10. Java 之异常

    异常概述 异常: 是在运行时期发生的不正常情况. 在 java 中用类的形式对不正常情况进行了描述和封装. 描述不正常情况的类, 就称为异常类. 异常体系 父类: Throwable (JDK 文档) ...