打网络赛

比赛前的准备工作要做好

确保 c++/java/python的编译器能用

打好模板,放在桌面

A. PERFECT NUMBER PROBLEM

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e8+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. int sum[maxn];
  20.  
  21. int main()
  22. {
  23. int n=,i,j;
  24. for (i=;i<n;i++)
  25. for (j=i;j<n;j+=i)
  26. sum[j]+=i;
  27. for (i=;i<n;i++)
  28. if (sum[i]==i+i)
  29. printf("%d ",i);
  30. return ;
  31. }
  32. /*
  33. 6 28 496 8128 33550336
  34. Process returned 0 (0x0) execution time : 24.646 s
  35. */

较差的打表方法

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e4+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. int main()
  20. {
  21. ///我相信很大一部分同学是网上找答案的,这不好
  22. // printf("6\n28\n496\n8128\n33550336");
  23. ll sum,i,j,k;
  24. for (i=;i<=;i++)
  25. {
  26. sum=;
  27. k=sqrt(i);
  28. for (j=;j<=k;j++)
  29. if (i%j==)
  30. sum+=j+i/j;
  31. if (k*k==i)
  32. sum-=i;
  33. sum-=i;
  34. if (sum==i)
  35. printf("%d ",i);
  36. if (i%==)
  37. printf("i=%d\n",i);
  38. }
  39. return ;
  40. }
  41. /*
  42. 6 28 496 8128 33550336
  43. 18 min
  44. */

C. Angry FFF Party

fib(x) 逐渐变得很大

而fib(fib(x))更是如此,

感觉可以打表

于是用python打表验证一下

  1. import math
  2.  
  3.  
  4. a=/math.sqrt()
  5.  
  6. b=(+math.sqrt())/
  7.  
  8. c=(-math.sqrt())/
  9.  
  10. a
  11.  
  12. 0.4472135954999579
  13.  
  14. a
  15.  
  16. for n in range(,):
  17.  
  18. print(n)
  19.  
  20. x=a*(pow(b,n) - pow(c,n))
  21.  
  22. x=round(x)
  23.  
  24. print(x)
  25.  
  26.  
  27. y=a*(pow(b,x) - pow(c,x))
  28.  
  29. print(y)
  30.  
  31. print()
  32.  
  33. 1.0
  34.  
  35. 1.0
  36.  
  37. 1.0
  38.  
  39. 2.0
  40.  
  41. 5.000000000000001
  42.  
  43. 21.000000000000004
  44.  
  45. 233.00000000000006
  46.  
  47. 10946.000000000007
  48.  
  49. 5702887.0000000065
  50.  
  51. 139583862445.00024
  52.  
  53. 1.7799794160047194e+18
  54.  
  55. 5.555654042242954e+29
  56.  
  57. 2.2112364063039317e+48
  58.  
  59. 2.746979206949977e+78
  60.  
  61. 1.3582369791278544e+127

开始用java写 BigInteger

  1. import java.math.BigInteger;
  2. import java.util.Scanner;
  3.  
  4. public class Main {
  5. static class mat {
  6. BigInteger [][]a=new BigInteger[][];
  7. mat() {
  8. a[][]=a[][]=a[][]=a[][]=BigInteger.ZERO;
  9. }
  10. static mat mul(mat a,mat b) {
  11. mat c=new mat();
  12. for (int k=;k<;k++)
  13. for (int i=;i<;i++)
  14. for (int j=;j<;j++)
  15. c.a[i][j]=c.a[i][j].add(a.a[i][k].multiply(b.a[k][j]));
  16. return c;
  17. }
  18. void print() {
  19. for (int i=;i<;i++) {
  20. for (int j=;j<;j++)
  21. System.out.print(a[i][j]+" ");
  22. System.out.println();
  23. }
  24. System.out.println();
  25. }
  26. }
  27.  
  28. static BigInteger _pow(int n) {
  29. mat a=new mat();
  30. mat b=new mat();
  31. a.a[][]=BigInteger.ONE;
  32. a.a[][]=BigInteger.ZERO;
  33. a.a[][]=BigInteger.ZERO;
  34. a.a[][]=BigInteger.ONE;
  35.  
  36. b.a[][]=BigInteger.ONE;
  37. b.a[][]=BigInteger.ONE;
  38. b.a[][]=BigInteger.ONE;
  39. b.a[][]=BigInteger.ZERO;
  40.  
  41. while (n>) {
  42. if (n%==)
  43. a=mat.mul(a,b);
  44. b=mat.mul(b,b);
  45. // b.print();
  46. n>>=;
  47. }
  48. return a.a[][];
  49. }
  50.  
  51. public static void main(String[] args) throws Exception {
  52.  
  53. int i,len=;//
  54. int []a=new int[];
  55. BigInteger []b=new BigInteger[];
  56. StringBuffer s=new StringBuffer("");
  57. for (i=;i<len;i++)
  58. s=s.append("");
  59. String ss=new String(s);
  60. BigInteger maxb=new BigInteger(ss);
  61. // System.out.println(maxb);
  62.  
  63. // _pow(10);
  64.  
  65. a[]=a[]=;
  66. mat ma = new mat();
  67. for (i=;i<;i++) {
  68. if (i<)
  69. a[i]=;
  70. else
  71. a[i]=a[i-]+a[i-];
  72. // System.out.println(a[i]);
  73. b[i]=_pow(a[i]);
  74. // if (i<10)
  75. // System.out.println(b[i]);
  76. if (b[i].compareTo(maxb)>=)
  77. break;
  78. }
  79. // System.out.println("i="+i);
  80. int maxg=i;
  81.  
  82. Scanner in=new Scanner(System.in);
  83. int t=in.nextInt();
  84. BigInteger m;
  85.  
  86. int []num=new int[];
  87. int g=;
  88. BigInteger[] bb=new BigInteger[];
  89. for (i=;i<=;i++)
  90. bb[i]=new BigInteger(Integer.toString(i));
  91. String []pr=new String[];
  92.  
  93. /*
  94. 1 1 1 2 5 21
  95. */
  96. pr[]="";
  97. pr[]="1 2";
  98. pr[]="1 2 3";
  99. pr[]="1 2 4";
  100. pr[]="1 2 3 4";
  101. for (i=;i<=;i++)
  102. pr[i]=pr[i-]+"";
  103.  
  104. while (t-->) {
  105. m=in.nextBigInteger();
  106.  
  107. g=;
  108. if (m.compareTo(bb[])>) {
  109. for (i=maxg;i>;i--)
  110. if (m.compareTo(b[i])>=) {
  111. m=m.subtract(b[i]);
  112. g=g+;
  113. num[g]=i;
  114. }
  115. }
  116. if (m.compareTo(bb[])>)
  117. System.out.println(-);
  118. else {
  119. for (i=;i<=;i++)
  120. if (m.compareTo(bb[i])==)
  121. System.out.print(pr[i]);
  122. if (m.compareTo(bb[])!= && g!=)
  123. System.out.print(" ");
  124. if (g==)
  125. System.out.println();
  126. for (i=g;i>=;i--) {
  127. System.out.print(num[i]);
  128. if (i==)
  129. System.out.println();
  130. else
  131. System.out.print(" ");
  132. }
  133. }
  134. }
  135. }
  136. }
  137. /*
  138. 1 1 1 2 5 21
  139.  
  140. 1
  141. 1
  142. 1
  143. 2
  144. 5
  145. 21
  146. 233
  147. 10946
  148. 5702887
  149.  
  150. 100
  151. 1-10
  152. 11
  153. 21
  154. 27
  155. */

H. Coloring Game

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e4+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18. const ll mod=1e9+;
  19.  
  20. ll mul(ll a,ll b)
  21. {
  22. ll y=;
  23. while (b)
  24. {
  25. if (b&)
  26. y=y*a%mod;
  27. a=a*a%mod;
  28. b>>=;
  29. }
  30. return y;
  31. }
  32.  
  33. int main()
  34. {
  35. int n;
  36. scanf("%d",&n);
  37. if (n==)
  38. printf("");
  39. else
  40. printf("%lld",mul(,n-)*%mod);
  41. return ;
  42. }
  43. /*
  44. 1000000000
  45. */

K. MORE XOR

找规律

推公式较为复杂,据说用插板法

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e5+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. int f[][maxn],a[maxn];
  20.  
  21. int main()
  22. {
  23. // printf("%d",1^2^5^6^9^10);
  24. int T,n,q,i,j,k,x,y,s,t,v;
  25. scanf("%d",&T);
  26. while (T--)
  27. {
  28. scanf("%d",&n);
  29. for (i=;i<=n;i++)
  30. scanf("%d",&a[i]);
  31.  
  32. for (k=;k<;k++)
  33. for (i=(k==)?:k,j=;i<=n;i+=,j++)
  34. f[k][j]=f[k][j-]^a[i];
  35.  
  36. scanf("%d",&q);
  37. while (q--)
  38. {
  39. scanf("%d%d",&i,&j);
  40. y=(j-i+)%;
  41. if (y==)
  42. {
  43. ///i,i+4,i+8 ...
  44. x=i%;
  45. s=(i+)/;
  46. t=s+(j-i)/;
  47. printf("%d\n",f[x][t]^f[x][s-]);
  48. }
  49. else if (y==)
  50. {
  51. x=i%;
  52. s=(i+)/;
  53. t=s+(j-i)/;
  54. v=f[x][t]^f[x][s-];
  55.  
  56. i++;
  57. x=i%;
  58. s=(i+)/;
  59. t=s+(j-i)/;
  60. printf("%d\n",v^f[x][t]^f[x][s-]);
  61. }
  62. else if (y==)
  63. {
  64. i++;
  65. x=i%;
  66. s=(i+)/;
  67. t=s+(j-i)/;
  68. printf("%d\n",f[x][t]^f[x][s-]);
  69. }
  70. else
  71. printf("0\n");
  72. }
  73. }
  74. return ;
  75. }
  76. /*
  77. 1
  78. 10
  79. 1 2 3 4 5 6 7 8 9 10
  80. 100
  81. 1 7
  82. */
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e4+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. int n=;
  20.  
  21. struct node
  22. {
  23. int a[];
  24. node operator+(const node &y)
  25. {
  26. node z;
  27. for (int i=;i<=n;i++)
  28. z.a[i]=a[i]+y.a[i];
  29. return z;
  30. }
  31. }f[][][];
  32.  
  33. int main()
  34. {
  35. int i,j,k,l;
  36. int x=;
  37. for (i=;i<=n;i++)
  38. f[][i][i].a[i]=;
  39. for (l=;l<=x;l++)
  40. {
  41. // for (i=1;i<n;i++)
  42. // {
  43. // f[l][i][i]=f[l-1][i][i];
  44. // for (j=i+1;j<=n;j++)
  45. // f[l][i][j]=f[l][i][j-1]+f[l-1][j][j];
  46. // }
  47.  
  48. for (i=;i<=n;i++)
  49. for (j=i;j<=n;j++)
  50. {
  51. if (i!=j)
  52. f[l][i][j]=f[l][i][j-];
  53. for (k=i;k<=j;k++)
  54. f[l][i][j]=f[l][i][j]+f[l-][k][j];
  55. }
  56. }
  57. int y=;
  58. for (i=;i<=n;i++)
  59. {
  60. for (j=;j<=n;j++)
  61. // printf("%d%c",f[y][1][i].a[j],j==n?'\n':' ');
  62. printf("%d%c",f[y][][i].a[j] &,j==n?'\n':' ');
  63. }
  64. return ;
  65. }
  66. /*
  67. 1 0 0 0 0 0 0 0 0 0
  68. 1 1 0 0 0 0 0 0 0 0
  69. 0 1 0 0 0 0 0 0 0 0
  70. 0 0 0 0 0 0 0 0 0 0
  71. 1 0 0 0 1 0 0 0 0 0
  72. 1 1 0 0 1 1 0 0 0 0
  73. 0 1 0 0 0 1 0 0 0 0
  74. 0 0 0 0 0 0 0 0 0 0
  75. 1 0 0 0 1 0 0 0 1 0
  76. 1 1 0 0 1 1 0 0 1 1
  77.  
  78. 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  79. 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  80. 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  81. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  82. 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  83. 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  84. 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  85. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  86. 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
  87. 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0
  88. 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
  89. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  90. 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0
  91. 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0
  92. 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0
  93. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  94. 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0
  95. 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
  96. 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0
  97. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  98. */

M. Subsequence

序列自动机

非正统的写法:

1.从后往前,记录每一个字符最新出现的位置

2.贪心,找到第一个字符,在第一个字符位置之后找第二个字符,...

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e5+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. int f[maxn][],pre[maxn];
  20. char s[maxn];
  21.  
  22. int main()
  23. {
  24. int i,j,len,t;
  25. memset(pre,0xff,sizeof(pre));
  26. s[]='a';
  27. scanf("%s",s+);
  28. len=strlen(s+);
  29. for (i=len;i>=;i--)
  30. {
  31. for (j=;j<;j++)
  32. f[i][j]=pre[j];
  33. pre[s[i]]=i;
  34. }
  35. scanf("%d",&t);
  36. while (t--)
  37. {
  38. scanf("%s",s);
  39. len=strlen(s);
  40. j=f[][s[]];
  41. for (i=;i<len;i++)
  42. {
  43. if (j==-)
  44. break;
  45. j=f[j][s[i]];
  46. }
  47. if (j!=-)
  48. printf("YES\n");
  49. else
  50. printf("NO\n");
  51. }
  52. return ;
  53. }
  54. /*
  55.  
  56. */

C. Angry FFF Party

数位dp

原来的数据是完全无用的,
只需要火柴棒总数保持一致,
只需要对于每一位,火柴棒加的次数完全一样

不用考虑前导0
+0 -> +9
-0  -> +5

w为数字的位数,y使用的火柴数
f[w][y] 的最大值
f[w][y]=max(f[w-1][y-g[i]]+i*10^(w-1))    i=0..9
w<10,y<w*7+2

-11..1 无法改变
f[1][3]=-1
f[p][p*2+1]=-11..1
其它时候不用减法(至少可以节省一根火柴,使负号变为加号)
这个不成立,在第一个数时(潜在加法)
预处理

对于当前的前x个数字,y为使用的火柴棒总数,以此最大的值
对于第x个数字,位数为w
a[x][y]=max(a[x-1][z]+f[w][z-y])
x<=50,y<=7*50+2*49=448
[49个加号,50个数]

易错点:
+/- 不能单独每一位,而要整体求

正确通过 2019-04-21 00:57 5ms 448kB c++14
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <set>
  8. #include <map>
  9. #include <queue>
  10. #include <iostream>
  11. using namespace std;
  12.  
  13. #define ll long long
  14.  
  15. const int maxn=1e4+;
  16. const int inf=1e9;
  17. const double eps=1e-;
  18.  
  19. /**
  20. 其实最多只有9位,
  21. 是小于10^9,没有等于
  22.  
  23. 999999999+999999999+...
  24. 超过int
  25. **/
  26.  
  27. int g[]={,,,,,,,,,};
  28. int f[][];
  29. int mul[];
  30. ll a[][];
  31. int fv[];
  32. int add[];
  33. char s[];
  34.  
  35. int main()
  36. {
  37. bool vis;
  38. int i,j,k,l,maxw,w,t,n,tot,sum,c;
  39.  
  40. // printf("%d\n",'+');///43
  41. // printf("%d\n",'-');///45
  42. add[]=,add[]=;
  43. for (i=;i<+;i++)
  44. add[i]=g[i-];
  45.  
  46. mul[]=;
  47. for (i=;i<=;i++)
  48. mul[i]=mul[i-]*;
  49.  
  50. fv[]=-;
  51. for (i=;i<=;i++)
  52. fv[i]=fv[i-]*-;
  53.  
  54. memset(f,0x8f,sizeof(f));
  55. f[][]=;///+
  56. for (i=;i<=;i++)
  57. {
  58. maxw=(i-)*+;
  59. for (j=;j<=maxw;j++)
  60. for (l=;l<=;l++) ///或者只要用火柴数在一个数量时最大的数即可
  61. f[i][j+g[l]]=max(f[i][j+g[l]],f[i-][j]+l*mul[i]);
  62. }
  63.  
  64. scanf("%d",&t);
  65. while (t--)
  66. {
  67. memset(a,0x8f,sizeof(a));
  68. scanf("%d",&n);
  69. scanf("%s",s);
  70. tot=;
  71. vis=;
  72. sum=;
  73. a[][]=;
  74. i=;
  75. c=;
  76. for (w=;w<=n;w++)
  77. {
  78. tot+=add[s[w]];
  79. if (s[w]=='+' || s[w]=='-' || w==n)
  80. {
  81. c++;
  82. maxw=i*+;
  83. for (j=;j<=sum;j++)
  84. for (k=;k<=maxw;k++)
  85. ///f[i][k](int memset)相比a[j](ll memset)小很多,减很多次,仍不会到达下界
  86. a[c][j+k]=max(a[c][j+k],a[c-][j]+f[i][k]); ///可以使用滚动数组
  87.  
  88. if (vis)
  89. for (j=;j<=sum;j++)
  90. a[c][j+*i+]=max(a[c][j+*i+],a[c-][j]+fv[i]);
  91.  
  92. sum+=maxw; ///当然也可以求出tot后再求
  93. vis=;
  94. i=;
  95. continue;
  96. }
  97. else
  98. i++;
  99. }
  100. printf("%lld\n",a[c][tot+]); ///第一个加号是没有的
  101. }
  102. return ;
  103. }
  104. /*
  105. 10
  106. 11
  107. 100000000+9
  108. 13
  109. 111-111111-11
  110. 20
  111. 100000000-99999999+1
  112. 36
  113. 10000000+12345+0+1+2+3+4+5+6+7+8+9
  114.  
  115. */

I. Max answer

单调栈+线段树

单调栈
找到一个数左边/右边的第一个大于其的数
把数列出来,容易找到方法
7 8 9 5(则9 8 7 出栈并赋值)

线段树
[l,r]区间 数为d 包含d的最大区间
sum[query_max(d,r)] - sum[query_min(l,d-1)]

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <set>
  7. #include <map>
  8. #include <list>
  9. #include <queue>
  10. #include <vector>
  11. #include <bitset>
  12. #include <algorithm>
  13. #include <iostream>
  14. using namespace std;
  15. #define ll long long
  16.  
  17. const double eps=1e-;
  18. const int maxn=5e5+;
  19. const ll inf=1e18;
  20.  
  21. int a[maxn],lef[maxn],rig[maxn],st[maxn],maxnum[maxn<<],minnum[maxn<<];
  22. ll sum[maxn];
  23.  
  24. void build(int ind,int l,int r)
  25. {
  26. if (l==r)
  27. maxnum[ind]=minnum[ind]=l;
  28. else
  29. {
  30. int m=(l+r)>>;
  31. build(ind<<,l,m);
  32. build(ind<<|,m+,r);
  33. if (sum[ maxnum[ind<<] ] > sum[ maxnum[ind<<|] ])
  34. maxnum[ind]=maxnum[ind<<];
  35. else
  36. maxnum[ind]=maxnum[ind<<|];
  37.  
  38. if (sum[ minnum[ind<<] ] < sum[ minnum[ind<<|] ])
  39. minnum[ind]=minnum[ind<<];
  40. else
  41. minnum[ind]=minnum[ind<<|];
  42. }
  43. }
  44.  
  45. int query_max(int ind,int l,int r,int x,int y)
  46. {
  47. if (x>y)
  48. return ;
  49. if (x<=l && r<=y)
  50. return maxnum[ind];
  51. int m=(l+r)>>,b=-;
  52. if (x<=m)
  53. b=query_max(ind<<,l,m,x,y);
  54. if (m<y)
  55. {
  56. if (b==-)
  57. return query_max(ind<<|,m+,r,x,y);
  58. else
  59. {
  60. int c=query_max(ind<<|,m+,r,x,y);
  61. if (sum[b]>sum[c])
  62. return b;
  63. return c;
  64. }
  65. }
  66. return b; ///
  67. }
  68.  
  69. int query_min(int ind,int l,int r,int x,int y)
  70. {
  71. if (x>y)
  72. return ;
  73. if (x<=l && r<=y)
  74. return minnum[ind];
  75. int m=(l+r)>>,b=-;
  76. if (x<=m)
  77. b=query_min(ind<<,l,m,x,y);
  78. if (m<y)
  79. {
  80. if (b==-)
  81. return query_min(ind<<|,m+,r,x,y);
  82. else
  83. {
  84. int c=query_min(ind<<|,m+,r,x,y);
  85. if (sum[b]<sum[c])
  86. return b;
  87. return c;
  88. }
  89. }
  90. return b; ///
  91. }
  92.  
  93. int main()
  94. {
  95. int n,i,g;
  96. ll r;
  97. scanf("%d",&n);
  98. for (i=;i<=n;i++)
  99. scanf("%d",&a[i]);
  100.  
  101. g=;
  102. for (i=;i<=n;i++)
  103. {
  104. while (g> && a[st[g]]>a[i])
  105. {
  106. rig[st[g]]=i;
  107. g--;
  108. }
  109. st[++g]=i;
  110. sum[i]=sum[i-]+a[i];
  111. }
  112.  
  113. g=;
  114. for (i=n;i>=;i--)
  115. {
  116. while (g> && a[st[g]]>a[i])
  117. {
  118. lef[st[g]]=i;
  119. g--;
  120. }
  121. st[++g]=i;
  122. }
  123.  
  124. build(,,n);
  125. r=-inf;
  126. for (i=;i<=n;i++)
  127. {
  128. if (rig[i]==)
  129. rig[i]=n+;
  130. if (a[i]>=)
  131. r=max(r,a[i]*(sum[rig[i]-]-sum[lef[i]]));
  132. else
  133. r=max(r,a[i]*(sum[query_min(,,n,i,rig[i]-)]-max(0ll,sum[query_max(,,n,lef[i]+,i-)])));///<
  134. }
  135. printf("%lld",r);
  136. return ;
  137. }
  138. /*
  139. 5
  140. -2 1 -3 -4 3
  141.  
  142. 6
  143. -1 -2 -3 -4 -5 -6
  144.  
  145. 3
  146. -1 -3 -2
  147.  
  148. 1
  149. -3
  150. */

J. Distance on the tree

1.树剖

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <iostream>
  8. using namespace std;
  9. #define ll long long
  10. const double eps=1e-;
  11. const int maxn=1e5+;
  12.  
  13. ///°´ÕձߵĴóСÅÅÐò
  14. ///树剖: 边 而不是 点
  15.  
  16. struct node
  17. {
  18. int d;
  19. node *to;
  20. }*e[maxn];
  21.  
  22. struct rec
  23. {
  24. int u,v,w,num,mode;
  25. bool operator<(const rec &y) const
  26. {
  27. if (w==y.w)
  28. return mode<y.mode;
  29. return w<y.w;
  30. }
  31. }b[maxn+maxn];
  32.  
  33. int sum[maxn];
  34.  
  35. int fa[maxn],dep[maxn],siz[maxn],son[maxn];
  36. int id[maxn],top[maxn];
  37. int n,num;
  38. bool vis[maxn];
  39. int tr[maxn<<];
  40.  
  41. void dfs1(int d)
  42. {
  43. int dd;
  44. node* p=e[d];
  45. vis[d]=;
  46. siz[d]=;
  47. while (p)
  48. {
  49. dd=p->d;
  50. if (!vis[dd])
  51. {
  52. fa[dd]=d;
  53. dep[dd]=dep[d]+;
  54. dfs1(dd);
  55. siz[d]+=siz[dd];
  56. if (siz[dd]>siz[son[d]])
  57. son[d]=dd;
  58. }
  59. p=p->to;
  60. }
  61. }
  62.  
  63. void dfs2(int d,int topd)
  64. {
  65. id[d]=++num;
  66. top[d]=topd;
  67. if (son[d]!=)
  68. {
  69. int dd;
  70. node *p;
  71. dfs2(son[d],topd);
  72.  
  73. p=e[d];
  74. while (p)
  75. {
  76. dd=p->d;
  77. if (dd!=son[d] && dd!=fa[d])
  78. dfs2(dd,dd);
  79. p=p->to;
  80. }
  81. }
  82. }
  83.  
  84. void update(int ind,int l,int r,int x)
  85. {
  86. tr[ind]++;
  87. if (l==r)
  88. return;
  89. int m=(l+r)>>;
  90. if (x<=m)
  91. update(ind<<,l,m,x);
  92. else
  93. update(ind<<|,m+,r,x);
  94. }
  95.  
  96. int query(int ind,int l,int r,int x,int y)
  97. {
  98. if (x<=l && r<=y)
  99. return tr[ind];
  100. int m=(l+r)>>,sum=;
  101. if (x<=m)
  102. sum+=query(ind<<,l,m,x,y);
  103. if (m<y)
  104. sum+=query(ind<<|,m+,r,x,y);
  105. return sum;
  106. }
  107.  
  108. int cal(int x,int y)
  109. {
  110. int sum=;
  111. while (top[x]!=top[y])
  112. {
  113. if (dep[top[x]]<dep[top[y]])
  114. swap(x,y);
  115. sum+=query(,,n,id[top[x]],id[x]);
  116. x=fa[top[x]];
  117. }
  118.  
  119. if (dep[x]<dep[y])
  120. swap(x,y);
  121. ///u,v not the same
  122. ///减去根节点
  123. return sum+query(,,n,id[y]+,id[x]);
  124. }
  125.  
  126. int main()
  127. {
  128. node *p;
  129. int m,i,u,v;
  130. scanf("%d%d",&n,&m);
  131. for (i=;i<n;i++)
  132. {
  133. scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
  134. b[i].num=i;
  135. b[i].mode=;
  136.  
  137. p=new node();
  138. p->d=b[i].v;
  139. p->to=e[b[i].u];
  140. e[b[i].u]=p;
  141.  
  142. p=new node();
  143. p->d=b[i].u;
  144. p->to=e[b[i].v];
  145. e[b[i].v]=p;
  146. }
  147. for (i=n;i<n+m;i++)
  148. {
  149. scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
  150. b[i].num=i;
  151. b[i].mode=;
  152. }
  153. sort(b+,b+n+m);
  154.  
  155. fa[]=;
  156. dfs1();
  157.  
  158. dfs2(,);
  159.  
  160. for (i=;i<n+m;i++)
  161. {
  162. u=b[i].u;
  163. v=b[i].v;
  164. if (dep[u]<dep[v])
  165. swap(u,v);
  166.  
  167. ///往距离远的点加值
  168. if (b[i].num<n)
  169. update(,,n,id[u]);
  170. else
  171. sum[b[i].num-n+]=cal(u,v);
  172. }
  173.  
  174. for (i=;i<=m;i++)
  175. printf("%d\n",sum[i]);
  176. return ;
  177. }

2.主席树

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <string>
  6. #include <algorithm>
  7. #include <iostream>
  8. using namespace std;
  9.  
  10. #define ll long long
  11. const double eps=1e-;
  12. const int maxn=1e5+;
  13. const int maxv=1e9;
  14.  
  15. ///1-i中的所有数 1-fa(j) -> 1-j 链 主席树
  16.  
  17. struct node
  18. {
  19. int d,len,num;
  20. node *to;
  21. node *opp;
  22. int c;
  23. }*e[maxn],*point[maxn];
  24.  
  25. struct rec
  26. {///any d,dd 经历两次 可以选择d中加入编号比其大的
  27. int l,r,sum;
  28. }tr[maxn*];
  29.  
  30. int sum[maxn],fa[maxn],be[maxn],num;
  31. bool vis[maxn];
  32.  
  33. void build(int ind_old,int ind,int l,int r,int x)
  34. {
  35. if (l==r) ///single
  36. {
  37. tr[ind].sum=tr[ind_old].sum+;
  38. return;
  39. }
  40. int m=(l+r)>>;
  41. if (x<=m)
  42. {
  43. tr[ind].r=tr[ind_old].r;
  44. tr[ind].l=++num;
  45. build(tr[ind_old].l,tr[ind].l,l,m,x);
  46. }
  47. else
  48. {
  49. tr[ind].l=tr[ind_old].l;
  50. tr[ind].r=++num;
  51. build(tr[ind_old].r,tr[ind].r,m+,r,x);
  52. }
  53. tr[ind].sum=tr[tr[ind].l].sum + tr[tr[ind].r].sum;
  54. }
  55.  
  56. int query(int ind,int l,int r,int k) ///[1,k]
  57. {
  58. if (r<=k)
  59. return tr[ind].sum;
  60. int m=(l+r)>>,sum=;
  61. if (tr[ind].l!=) ///存在(该点在线段树中被创建)
  62. sum+=query(tr[ind].l,l,m,k);
  63. if (m<k && tr[ind].r!=)
  64. sum+=query(tr[ind].r,m+,r,k);
  65. return sum;
  66. }
  67.  
  68. void dfs(int d)
  69. {
  70. node *p=e[d];
  71. int dd;
  72. vis[d]=;
  73. while (p)
  74. {
  75. dd=p->d;
  76. if (!vis[dd])
  77. {
  78. be[dd]=++num;
  79. build(be[d],be[dd],,maxv,p->len);
  80. dfs(dd);
  81. }
  82. p=p->to;
  83. }
  84. }
  85.  
  86. int getf(int d)
  87. {
  88. if (fa[d]==d)
  89. return d;
  90. fa[d]=getf(fa[d]);
  91. return fa[d];
  92. }
  93.  
  94. void lca(int d)
  95. {
  96. int dd,x,y;
  97. node *p=e[d];
  98. vis[d]=;
  99. while (p)
  100. {
  101. dd=p->d;
  102. if (!vis[dd])
  103. {
  104. lca(dd);
  105. x=getf(d);
  106. y=getf(dd);
  107. fa[y]=x;
  108. }
  109. p=p->to;
  110. }
  111.  
  112. p=point[d];
  113. while (p)
  114. {
  115. dd=p->d;
  116. ///也许出现一次,也许出现两次
  117. if (vis[dd] && p->opp->c==)
  118. {
  119. sum[p->num]-=query(be[getf(dd)],,maxv,p->len)*;
  120. p->c=;
  121. }
  122.  
  123. p=p->to;
  124. }
  125. }
  126.  
  127. int main()
  128. {
  129. node *p,*pp;
  130. int n,m,u,v,w,k,i;
  131. scanf("%d%d",&n,&m);
  132. for (i=;i<=n;i++)
  133. fa[i]=i;
  134.  
  135. for (i=;i<n;i++)
  136. {
  137. scanf("%d%d%d",&u,&v,&w);
  138.  
  139. p=new node();
  140. p->d=v;
  141. p->len=w;
  142. p->to=e[u];
  143. e[u]=p;
  144.  
  145. p=new node();
  146. p->d=u;
  147. p->len=w;
  148. p->to=e[v];
  149. e[v]=p;
  150. }
  151.  
  152. num=;
  153. be[]=;
  154.  
  155. dfs();
  156.  
  157. for (i=;i<=m;i++)
  158. {
  159. scanf("%d%d%d",&u,&v,&k);
  160.  
  161. p=new node();
  162. pp=new node();
  163.  
  164. p->d=v;
  165. p->len=k;
  166. p->num=i;
  167. p->to=point[u];
  168. p->opp=pp;
  169. p->c=;
  170. point[u]=p;
  171.  
  172. pp->d=u;
  173. pp->len=k;
  174. pp->num=i;
  175. pp->to=point[v];
  176. pp->opp=p;
  177. pp->c=;
  178. point[v]=pp;
  179.  
  180. sum[i]=query(be[u],,maxv,k) + query(be[v],,maxv,k);
  181.  
  182. // printf("%d %d\n",query(be[u],1,maxv,k),query(be[v],1,maxv,k));
  183. }
  184.  
  185. memset(vis,,sizeof(vis));
  186. lca();
  187.  
  188. for (i=;i<=m;i++)
  189. printf("%d\n",sum[i]);
  190. return ;
  191. }

The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest的更多相关文章

  1. 2019The Preliminary Contest for ICPC China Nanchang National Invitational

    The Preliminary Contest for ICPC China Nanchang National Invitational 题目一览表 考察知识点 I. Max answer 单调栈+ ...

  2. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  3. The Preliminary Contest for ICPC China Nanchang National Invitational

    目录 Contest Info Solutions A. PERFECT NUMBER PROBLEM D. Match Stick Game G. tsy's number H. Coloring ...

  4. The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题目大意:一个区间的值等于该区间的和乘以区间的最小值.给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大 ...

  5. The Preliminary Contest for ICPC China Nanchang National Invitational I题

    Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values ...

  6. Max answer(The Preliminary Contest for ICPC China Nanchang National Invitational)

    Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values ...

  7. The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer单调栈

    题面 题意:一个5e5的数组,定义一个区间的值为 这个区间的和*这个区间的最小值,注意数组值有负数有正数,求所有区间中最大的值 题解:如果全是正数,那就是原题 POJ2796 单调栈做一下就ok 我们 ...

  8. 2019 The Preliminary Contest for ICPC China Nanchang National Invitational(A 、H 、I 、K 、M)

    A. PERFECT NUMBER PROBLEM 题目链接:https://nanti.jisuanke.com/t/38220 题意: 输出前五个完美数 分析: 签到.直接百度完美数输出即可 #i ...

  9. 计蒜客 38228. Max answer-线段树维护单调栈(The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer 南昌邀请赛网络赛) 2019ICPC南昌邀请赛网络赛

    Max answer Alice has a magic array. She suggests that the value of a interval is equal to the sum of ...

随机推荐

  1. Asp.Net登陆记住用户功能实现

    1.效果和原理 原理是利用Asp.net的Cookies.选中CheckBox,把输入的用户名和密码用Cookies存储起来,设置过期时间7天,超过时间自动清除Cookie信息. 2.前台代码 < ...

  2. spring基本知识

    什么是spring: spring就是以IOC反转控制和AOP面向切面编程为内核,使用基本的JavaBean来完成以前由EJB完成的工作. spring框架的优点: (1)方便耦合,简化开发:spri ...

  3. Lcd(一)显示原理

    一.LCD控制原理 S5PV210处理器中自带LCD控制器,控制LCD的显示,把 LCD 图像数据从一个位于系统内存的 video buffer 传送到一个外部的 LCD 驱动器接口. 类型: STN ...

  4. python3 OrderedDict类(有序字典)

    创建有序字典 import collections dic = collections.OrderedDict() dic['k1'] = 'v1' dic['k2'] = 'v2' dic['k3' ...

  5. Canvas中的非零环绕

    先上图 当要填充图形时,必须区分开哪些部分是覆盖的,哪些是空的,根据绘制的方向可以判断出来 非零环绕规则:对于路径中指定范围区域,从该区域内部画一条足够长的线段,使此线段的完全落在路径范围之外. 非零 ...

  6. #021 Java复习第一天

    上学期在慧河工作室学习简单过java到面向对象就停止了 现在有事情又要用到java发现全忘了..... 快速复习一下 网课PPT 计算机: 硬件 + 软件 主要硬件: cpu :cpu是一个计算机的运 ...

  7. 英语口语练习系列-C17-Love story

    词汇学习 break [breɪk] v. 打破 broke (过去式) The glass broke. 玻璃杯碎了. My watch broke. 我的表坏了. break the law 违法 ...

  8. IDF-简单题目writeup

    1. 被改错的密码 原题: 从前有一个熊孩子入侵了一个网站的[数据库],找到了管理员密码,手一抖在[数据库]中修改了一下,现在的密码变成了ca9cc444e64c8116a30la00559c042b ...

  9. IDEA包名显示设置

    项目结构视图右上角那个齿轮 选择[Compact Empty Middle Packages],包会合并显示 [Hide Empty Middle Packages]去掉前面的√,不分层级显示

  10. centos7下git版本升级及gitlab安装

    centos系统自带的git版本过低,当使用git拉取.推送.克隆的时候可能会报错,常见的错误: error: The requested URL returned error: 401 Unauth ...