CF1209

A B

水题不管

C

因为要求最终整个序列是要单调的

所以我们就考虑枚举断点\(x\)

之后把\(<x\)的数放到第一个集合

把\(> x\)的数放到第二个集合

至于\(=x\)的数

他能放到第一个集合当且仅当后面没有\(<x\)的数

否则就必须放到第二个集合

在放的时候判断合法性即可

(枚举把\(0-9\)写成了\(1 - 10\)就没了QAQ

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cctype>
  7. #include<vector>
  8. #include<ctime>
  9. #include<cmath>
  10. #define LL long long
  11. #define pii pair<int,int>
  12. #define mk make_pair
  13. #define fi first
  14. #define se second
  15. using namespace std;
  16. const int N = 5e5 + 3;
  17. char s[N];
  18. int a[N];
  19. int sum[N][11];
  20. int belong[N];
  21. int n;
  22. inline int read(){
  23. int v = 0,c = 1;char ch = getchar();
  24. while(!isdigit(ch)){
  25. if(ch == '-') c = -1;
  26. ch = getchar();
  27. }
  28. while(isdigit(ch)){
  29. v = v * 10 + ch - 48;
  30. ch = getchar();
  31. }
  32. return v * c;
  33. }
  34. inline bool check(int x){
  35. // printf("x::%d\n",x);
  36. int now1 = -1,now2 = -1;
  37. for(int i = 1;i <= n;++i){
  38. // printf("%d %d %d\n",i,now1,now2);
  39. if(a[i] < x && a[i] < now1) return 0;
  40. if(a[i] > x && a[i] < now2) return 0;
  41. if(a[i] != x){
  42. if(a[i] < x) now1 = max(now1,a[i]),belong[i] = 1;
  43. else if(a[i] > x) now2 = max(now2,a[i]),belong[i] = 2;
  44. }
  45. if(a[i] == x){
  46. bool flag = 0;
  47. for(int j = 0;j <= x - 1;++j) if(sum[i][j]) flag = 1;
  48. if((!flag) && (a[i] >= now1)) {
  49. now1 = a[i],belong[i] = 1;
  50. }
  51. else{
  52. if(now2 > a[i]) return 0;
  53. now2 = max(now2,a[i]),belong[i] = 2;
  54. }
  55. }
  56. }
  57. return 1;
  58. }
  59. int main(){
  60. int T = read();
  61. while(T--){
  62. bool flag = 0;
  63. n = read();
  64. scanf("%s",s + 1);
  65. for(int i = 1;i <= n;++i) a[i] = s[i] - '0';
  66. for(int i = n;i >= 1;--i){
  67. for(int j = 0;j <= 9;++j) sum[i][j] = sum[i + 1][j];
  68. sum[i][a[i]]++;
  69. }
  70. for(int i = 0;i <= 9;++i){
  71. if(check(i)){
  72. for(int j = 1;j <= n;++j) printf("%d",belong[j]);
  73. printf("\n");
  74. flag = 1;
  75. break;
  76. }
  77. }
  78. if(!flag) printf("-\n");
  79. for(int i = 1;i <= n;++i){
  80. for(int j = 0;j <= 9;++j) sum[i][j] = 0;
  81. }
  82. }
  83. return 0;
  84. }
  85.  

D

首先我们发现把\(a_i\)向\(b_i\)连边最后会形成若干个连通块

每个连通块的大小 - 1就是这个连通块的贡献

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cctype>
  7. #include<vector>
  8. #include<ctime>
  9. #include<cmath>
  10. #define LL long long
  11. #define pii pair<int,int>
  12. #define mk make_pair
  13. #define fi first
  14. #define se second
  15. using namespace std;
  16. const int N = 5e5 + 3;
  17. struct node{
  18. int ai;
  19. int bi;
  20. }a[N];
  21. vector <int> G[N];
  22. int n,k;
  23. bool flag1[N],flag2[N];
  24. inline int read(){
  25. int v = 0,c = 1;char ch = getchar();
  26. while(!isdigit(ch)){
  27. if(ch == '-') c = -1;
  28. ch = getchar();
  29. }
  30. while(isdigit(ch)){
  31. v = v * 10 + ch - 48;
  32. ch = getchar();
  33. }
  34. return v * c;
  35. }
  36. queue <int> q;
  37. int ans = 0;
  38. inline void dfs(int x){
  39. flag1[x] = 1;ans++;
  40. for(int i = 0;i < (int)G[x].size();++i){
  41. int y = G[x][i];
  42. if(!flag1[y]) dfs(y);
  43. }
  44. }
  45. int main(){
  46. n = read(),k = read();
  47. for(int i = 1;i <= k;++i){
  48. a[i].ai = read();
  49. a[i].bi = read();
  50. G[a[i].ai].push_back(a[i].bi);
  51. G[a[i].bi].push_back(a[i].ai);
  52. }
  53. for(int i = 1;i <= n;++i) if(!flag1[i]) ans--,dfs(i);
  54. cout << k - ans;
  55. }

E1E2

首先观察发现\(n\)特别小,当一个数小于等于\(20\)的时候第一反应就是要考虑状压

一个特别重要的性质

我们把所有的列按照这一列的最大值从大到小跑徐之后

最多只有前\(n\)列有用

也就是说

$n\times m \(的矩阵变成了\)n \times n$的

我们设\(f_{i,S}\)表示前\(i\)列,\(S\)这个状态对应的行的最大值已经确定的最大贡献,

\(g_{i,S}\)表示从第\(i\)列取出能够表示\(S\)这个集合的最大值

转移

\[f_{i,S} = \max_{T\subseteq S} f_{i - 1,S - T}+g_{i,T}
\]

记下来考虑怎么求\(g\)

由于存在轮换的存在

我们枚举一个集合,然后把这个集合能够表示的所有的状态都尝试用这个集合的值去更新

比如

\(1101\)能够表示\(1101\),\(1110\),\(1011\),\(0111\)

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cctype>
  7. #include<vector>
  8. #include<ctime>
  9. #include<cmath>
  10. #define LL long long
  11. #define pii pair<int,int>
  12. #define mk make_pair
  13. #define fi first
  14. #define se second
  15. using namespace std;
  16. const int M = 21;
  17. const int N = 2003;
  18. int a[M][N];
  19. int b[M][M];
  20. int n,m;
  21. int f[13][(1 << 13) + 5];
  22. int g[13][(1 << 13) + 3];
  23. struct node{
  24. int maxx;
  25. int id;
  26. }row[N];
  27. inline bool cmp(node x,node y){
  28. return x.maxx > y.maxx;
  29. }
  30. inline int read(){
  31. int v = 0,c = 1;char ch = getchar();
  32. while(!isdigit(ch)){
  33. if(ch == '-') c = -1;
  34. ch = getchar();
  35. }
  36. while(isdigit(ch)){
  37. v = v * 10 + ch - 48;
  38. ch = getchar();
  39. }
  40. return v * c;
  41. }
  42. int main(){
  43. int T = read();
  44. while(T--){
  45. memset(g,0,sizeof(g));
  46. memset(f,0,sizeof(f));
  47. memset(row,0,sizeof(row));
  48. n = read(),m = read();
  49. for(int i = 1;i <= n;++i){
  50. for(int j = 1;j <= m;++j){
  51. a[i][j] = read();
  52. row[j].maxx = max(row[j].maxx,a[i][j]);
  53. row[j].id = j;
  54. }
  55. }
  56. sort(row + 1,row + m + 1,cmp);
  57. m = min(n,m);
  58. for(int i = 1;i <= n;++i){
  59. for(int j = 1;j <= m;++j)
  60. b[i][j] = a[i][row[j].id];
  61. }
  62. for(int j = 1;j <= m;++j){
  63. for(int i = 1;i < (1 << n);++i){
  64. int res = i;
  65. int sum = 0;
  66. for(int h = 0;h < n;++h) if(res & (1 << h)) sum += b[h + 1][j];
  67. for(int k = 0;k < n;++k){
  68. g[j][res] = max(g[j][res],sum);
  69. int nn = res;
  70. res = ((nn >> (n - 1)) & 1) | ((nn << 1) & ((1 << n) - 1));
  71. }
  72. }
  73. }
  74. for(int i = 0;i < m;++i){
  75. for(int j = 0;j < (1 << n);++j){
  76. int S = ((1 << n) - 1) ^ j;
  77. f[i + 1][j] = max(f[i + 1][j],f[i][j]);
  78. for(int son = S;son;son = (son - 1) & S){
  79. f[i + 1][j | son] = max(f[i + 1][j | son],f[i][j] + g[i + 1][son]);
  80. }
  81. }
  82. }
  83. printf("%d\n",f[m][(1 << n) - 1]);
  84. }
  85. return 0;
  86. }

G1

我们发现,如果存在这种东西

3 1 3 1 3

那么整个区间最终都会是同一个数

也就是说

我们设\(l_i\)表示\(i\)的第一次出现的位置,\(r_i\)表示\(i\)最后一次出现的位置

最后会出现这种情况

我们发现有交集的区间最终都会变成同一个数,变成那个数取决于这个区间中那个数出现次数最多

我们把所有的区间搞出跑一跑贪心

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cctype>
  7. #include<vector>
  8. #include<ctime>
  9. #include<cmath>
  10. #define LL long long
  11. #define pii pair<int,int>
  12. #define mk make_pair
  13. #define fi first
  14. #define se second
  15. using namespace std;
  16. const int N = 5e5 + 3;
  17. int a[N];
  18. int fir[N],las[N];
  19. int sum[N];
  20. int n,q;
  21. bool flag1 = 1,flag2 = 1;
  22. inline int read(){
  23. int v = 0,c = 1;char ch = getchar();
  24. while(!isdigit(ch)){
  25. if(ch == '-') c = -1;
  26. ch = getchar();
  27. }
  28. while(isdigit(ch)){
  29. v = v * 10 + ch - 48;
  30. ch = getchar();
  31. }
  32. return v * c;
  33. }
  34. int ans = 0x3f3f3f3f;
  35. struct node{
  36. int li;
  37. int ri;
  38. int id;
  39. };
  40. vector <node> G;
  41. inline bool cmp(node x,node y){
  42. return x.li < y.li || (x.li == y.li && x.ri > y.ri);
  43. }
  44. int main(){
  45. n = read(),q = read();
  46. for(int i = 1;i <= n;++i){
  47. a[i] = read();
  48. if(!fir[a[i]]) fir[a[i]] = i;
  49. las[a[i]] = i;
  50. sum[a[i]]++;
  51. }
  52. for(int i = 1;i <= 200000;++i){
  53. if(!fir[i]) continue;
  54. if(!las[i]) G.push_back((node){fir[i],fir[i],i});
  55. else G.push_back((node){fir[i],las[i],i});
  56. }
  57. sort(G.begin(),G.end(),cmp);
  58. int ans = 0;
  59. int now = 0;
  60. int nowr = -1;
  61. int len = 0;
  62. int from = 1;
  63. int maxx = 0;
  64. // for(int i = 0;i < (int)G.size();++i){
  65. // printf("%d %d %d\n",G[i].id,G[i].li,G[i].ri);
  66. // }
  67. while(now < G.size()){
  68. if(G[now].li > nowr){
  69. ans += nowr - from + 1 - maxx;
  70. from = nowr + 1;
  71. maxx = 0;
  72. maxx = max(maxx,sum[G[now].id]);
  73. nowr = G[now].ri;
  74. }
  75. else{
  76. nowr = max(nowr,G[now].ri);
  77. maxx = max(maxx,sum[G[now].id]);
  78. }
  79. now++;
  80. }
  81. ans += nowr - from + 1 - maxx;
  82. printf("%d\n",ans);
  83. return 0;
  84. }
  85.  

CF1209的更多相关文章

  1. CF1209题解

    E 每列都可以沿下滚动若干次,使得各行最大值之和最大 对每列的元素计算最大值,降序排,显然取前\(min(n,m)\)个列处理即可 比较巧妙的动规,设\(f(i,S)\)为前\(i\)列,已经确定最大 ...

随机推荐

  1. Python中的动态继承

    所谓动态继承,是指代码运行时再决定某个类的父类.某些场景下会用到,比如threading.Thread和multiprocessing.Process这两个类有很多同名的接口,可以实现某个子类动态继承 ...

  2. 洛谷P2062 分队问题

      这是一道普及/提高- 然后你懂的,贪心扫一遍就可以了. 不懂提交人数那么少. //Serene #include<algorithm> #include<iostream> ...

  3. bzoj1412 狼和羊的故事

    Description “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! O ...

  4. bzoj2073 PRZ

    Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍 ...

  5. Oracle日期

    oracle 日期格式 to_date("要转换的字符串","转换的格式")   两个参数的格式必须匹配,否则会报错. 即按照第二个参数的格式解释第一个参数. ...

  6. springboot 数据访问【转】【补】

    六.SpringBoot与数据访问 1.JDBC pom.xml配置 <dependencies> <dependency> <groupId>org.spring ...

  7. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十章:混合

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十章:混合 代码工程地址: https://github.com/j ...

  8. SDUT-2116_数据结构实验之链表一:顺序建立链表

    数据结构实验之链表一:顺序建立链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入N个整数,按照输入的顺序建立单链 ...

  9. uva 10566 Crossed Ladders (二分)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  10. redis 清除缓存