当前位置:   article > 正文

牛客多校3

牛客多校

C.Concatenation

题意:给定n个字符串,求一个将他们拼接起来的方案,使得结果的字典序最小。

分析:对n个字符串排序,ab前面的条件是ab<ba,为什么这样正反拼接是正确的呢?在S1为S2子串的情况下,我们要考虑把谁放在前面,那就比一比谁放前面更小就可以了。

代码:

不加&会超时!不加&会超时!不加&会超时!传引用传引用传引用!!!

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=2e6+6;
  4. int T,n,a[N];
  5. string s[N];
  6. int cmp(string &a, string &b)
  7. {
  8. string s1 = a + b, s2 = b + a;
  9. return s1 < s2;
  10. }
  11. int main()
  12. {
  13. cin>>n;
  14. for( int i=1; i<=n; ++i ) cin>>s[i];
  15. sort(s + 1, s + n + 1, cmp);
  16. for(int i = 1; i <= n; i++) cout << s[i];
  17. return 0;
  18. }

A.Ancestor

题意:给出两棵编号为1~n的树A和B,A、B树上每个节点均有一个权值,给出k个关键点的编号x1...xn,问有多少种方案使得去掉恰好一个关键点使得剩余关键点在树A上LCA的权值大于树B上LCA的权值。

分析:

       需要用到一个结论——树上多个点的LCA为这多个点中DFS序最大的点和DFS序最小的点的LCA。故可以先求出所给k个关键点的DFS序,然后枚举删去哪一个。记得枚举前预处理LCA,要不然会超时。预处理其实只用求3+3次就可以了,分别为:删掉A的DFS最小(Ahead),删掉A的DFS序最大(Atail),删掉A的DFS序中间元素。

        枚举每个点的时候 if-else 判断一下该点在A、B树中的地位即可。

代码:

(有点长,主要是因为A、B两棵树形态不同,所以需要分开求。)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. using ll=long long;
  4. const int MAXN=105000;
  5. int N,K,x,ans=0;
  6. int d1,d2;
  7. int w1[MAXN],w2[MAXN]; //存两棵树每个点的weight
  8. int key[MAXN];//题目中提到的K个key number
  9. int ds1[MAXN],ds2[MAXN];// 存dfs序 dfs sort
  10. int Log2[MAXN],faA[MAXN][30],faB[MAXN][30],depA[MAXN]={0},depB[MAXN]={0};//找LCA需要的一些数组
  11. bool visA[MAXN]={false},visB[MAXN]={false};//找LCA需要的一些数组
  12. vector< vector<int> > treeA,treeB;//存树
  13. vector< pair<int,int> > KDS1,KDS2;//第一个数存顶点的dfs序,第二个数存顶点编号
  14. void TOinput()
  15. {
  16. for(int i=1;i<=K;i++) cin>>key[i];
  17. for(int i=1;i<=N;i++) cin>>w1[i];
  18. for(int i=2;i<=N;i++)
  19. {
  20. cin>>x;
  21. treeA[x].push_back(i);
  22. treeA[i].push_back(x);
  23. }
  24. for(int i=1;i<=N;i++) cin>>w2[i];
  25. for(int i=2;i<=N;i++)
  26. {
  27. cin>>x;
  28. treeB[x].push_back(i);
  29. treeB[i].push_back(x);
  30. }
  31. }
  32. void do_pre()
  33. {
  34. Log2[1] = 0;
  35. for (int i = 2; i <= N; ++i)
  36. Log2[i] = Log2[i / 2] + 1;
  37. }
  38. void dfsA(int cur, int fath)
  39. {
  40. if (visA[cur]) return;
  41. visA[cur] = true;
  42. depA[cur] = depA[fath] + 1;
  43. faA[cur][0] = fath;
  44. ds1[cur]=d1++;
  45. for (int i = 1; i <= Log2[depA[cur]]; i++) faA[cur][i] = faA[faA[cur][i - 1]][i - 1];
  46. for (int i=0; i<treeA[cur].size();i++)
  47. dfsA(treeA[cur][i], cur);
  48. }
  49. void dfsB(int cur, int fath)
  50. {
  51. if (visB[cur]) return;
  52. visB[cur] = true;
  53. depB[cur] = depB[fath] + 1;
  54. faB[cur][0] = fath;
  55. ds2[cur]=d2++;
  56. for (int i = 1; i <= Log2[depB[cur]]; i++) faB[cur][i] = faB[faB[cur][i - 1]][i - 1];
  57. for (int i=0; i<treeB[cur].size();i++)
  58. dfsB(treeB[cur][i], cur);
  59. }
  60. int lcaAA(int a, int b)
  61. {
  62. if (depA[a] > depA[b]) swap(a, b);
  63. while (depA[a] != depA[b]) b = faA[b][Log2[depA[b] - depA[a]]];
  64. if (a == b) return a;
  65. for (int k = Log2[depA[a]]; k >= 0; k--)
  66. {
  67. if (faA[a][k] != faA[b][k]) a = faA[a][k], b = faA[b][k];
  68. }
  69. return faA[a][0];
  70. }
  71. int lcaBB(int a, int b)
  72. {
  73. if (depB[a] > depB[b]) swap(a, b);
  74. while (depB[a] != depB[b]) b = faB[b][Log2[depB[b] - depB[a]]];
  75. if (a == b) return a;
  76. for (int k = Log2[depB[a]]; k >= 0; k--)
  77. {
  78. if (faB[a][k] != faB[b][k]) a = faB[a][k], b = faB[b][k];
  79. }
  80. return faB[a][0];
  81. }
  82. void TOdelete()
  83. {
  84. sort(KDS1.begin(),KDS1.end());
  85. sort(KDS2.begin(),KDS2.end());
  86. int Ahead=KDS1[0].second,Atail=KDS1[K-1].second,Bhead=KDS2[0].second,Btail=KDS2[K-1].second;
  87. int A1,A2,A3,B1,B2,B3;
  88. A1=lcaAA(KDS1[1].second,Atail);//头被删了
  89. A2=lcaAA(Ahead,KDS1[K-2].second);//尾巴被删了
  90. A3=lcaAA(Ahead,Atail);//删的是中间的
  91. B1=lcaBB(KDS2[1].second,Btail);
  92. B2=lcaBB(Bhead,KDS2[K-2].second);
  93. B3=lcaBB(Bhead,Btail);
  94. for(int i=1;i<=K;i++)
  95. {
  96. int lcaA,lcaB;
  97. if(key[i]==Ahead) lcaA=A1;
  98. if(key[i]==Atail) lcaA=A2;
  99. if(key[i]!=Ahead && key[i]!=Atail) lcaA=A3;
  100. if(key[i]==Bhead) lcaB=B1;
  101. if(key[i]==Btail) lcaB=B2;
  102. if(key[i]!=Bhead && key[i]!=Btail) lcaB=B3;
  103. if(w1[lcaA]>w2[lcaB]) ans++;
  104. }
  105. }
  106. int main()
  107. {
  108. ios::sync_with_stdio(false);
  109. cin.tie(nullptr);
  110. cin>>N>>K;
  111. treeA.resize(N+10);
  112. treeB.resize(N+10);
  113. TOinput();
  114. do_pre();
  115. d1=1; d2=1;
  116. dfsA(1,0); for(int i=1;i<=K;i++) KDS1.push_back({ds1[key[i]],key[i]}); //把通过dfs得到的字典序存进去
  117. dfsB(1,0); for(int i=1;i<=K;i++) KDS2.push_back({ds2[key[i]],key[i]});
  118. TOdelete();//枚举 删去哪一个key number点
  119. cout<<ans;
  120. return 0;
  121. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/986521
推荐阅读
相关标签
  

闽ICP备14008679号