CF1208

打的话貌似能够涨分的样子?

A

水题

B

枚举左端点,看看右端点的最近位置

开一个类似于桶的东西维护一下上一次出现位置

左端点左边就删掉,否则就要将上一次出现的位置删掉

时间复杂度\(O(n^2)\)或者\(O(n^2logn)\)取决于是否离散化

貌似一个log就是二分答案

然后\(O(n)\)check一遍

  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<map>
  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 = 2003;
  17. int a[N];
  18. int pre[N];
  19. map <int,int> m;
  20. int n;
  21. inline int read(){
  22. int v = 0,c = 1;char ch = getchar();
  23. while(!isdigit(ch)){
  24. if(ch == '-') c = -1;
  25. ch = getchar();
  26. }
  27. while(isdigit(ch)){
  28. v = v * 10 + ch - 48;
  29. ch = getchar();
  30. }
  31. return v * c;
  32. }
  33. int main(){
  34. int ans = 0x3f3f3f3f;
  35. n = read();
  36. for(int i = 1;i <= n;++i){
  37. a[i] = read();
  38. if(!m[a[i]]) m[a[i]] = i;
  39. else pre[i] = m[a[i]];
  40. m[a[i]] = i;
  41. // printf("%d\n",pre[i]);
  42. }
  43. bool flag = 1;
  44. for(int i = 1;i <= n;++i){
  45. m.clear();
  46. int r = 0;
  47. for(int j = 0;j < i;++j){
  48. if(m[a[j]] == -1) {flag = 0;break;}
  49. m[a[j]] = -1;
  50. }
  51. if(!flag) break;
  52. for(int j = i;j <= n;++j){
  53. if(m[a[j]] == -1) r = max(r,j);
  54. else if(m[a[j]] != 0){
  55. r = max(r,m[a[j]]);
  56. m[a[j]] = j;
  57. }
  58. else m[a[j]] = j;
  59. }
  60. if(r != 0) ans = min(ans,r - i + 1);
  61. else ans = 0;
  62. }
  63. cout << ans;
  64. return 0;
  65. }

听说貌似有\(O(n)\)做法不大会

C

构造题

分成四块考虑,因为题目中保证是\(4\)的倍数

首先,如果没有\(0-n^2-1\)这个限制

这样子肯定符合要求

\(\begin{array}{cccc}{0} & {0} & {1} & {1} \\ {0} & {0} & {1} & {1} \\ {2} & {2} & {3} & {3} \\ {2} & {2} & {3} & {3}\end{array}\)

但是这样肯定不符合题意

那么我们就对于给每一部分编号

把这一部分整体+4

\(\begin{array}{cccc}{0} & {4} & {1} & {5} \\ {8} & {12} & {9} & {13} \\ {2} & {6} & {3} & {7} \\ {10} & {14} & {11} & {15}\end{array}\)

如果没有保证\(n\)是\(4\)的倍数,那么这样构造一定不对,因为每一行都有数出现了奇数次

由于每一行每一列

每个\(4\)的倍数都只被加了两次

异或起来都答案是没有影响的

那么我们照着这样子构造就好了

D

感觉D是个一眼题,CD应该换一下位置的

最右边的\(0\)对应的位置一定是\(1\)

然后把\(1\)的贡献去掉之后,最右边的\(0\)一定是\(2\)

以此类推

线段树搞一搞就好了

  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. #define LL long long
  10. #define pii pair<int,int>
  11. #define mk make_pair
  12. #define fi first
  13. #define se second
  14. using namespace std;
  15. const int N = 2e5 + 3;
  16. const LL INF = 1e15;
  17. LL dis[N];
  18. int an[N];
  19. int n,root;
  20. inline LL read(){
  21. LL v = 0,c = 1;char ch = getchar();
  22. while(!isdigit(ch)){
  23. if(ch == '-') c = -1;
  24. ch = getchar();
  25. }
  26. while(isdigit(ch)){
  27. v = v * 10 + ch - 48;
  28. ch = getchar();
  29. }
  30. return v * c;
  31. }
  32. struct Tree{
  33. int t;
  34. struct node{
  35. LL maxx;
  36. LL tag;int pos;
  37. int lc,rc;
  38. }a[N << 2];
  39. inline void pushup(int u){
  40. if(a[a[u].lc].maxx < a[a[u].rc].maxx) a[u].maxx = a[a[u].lc].maxx,a[u].pos = a[a[u].lc].pos;
  41. else a[u].maxx = a[a[u].rc].maxx,a[u].pos = a[a[u].rc].pos;
  42. }
  43. inline void pushdown(int u,int l,int r){
  44. if(!a[u].tag) return;
  45. a[a[u].lc].maxx += a[u].tag;
  46. a[a[u].rc].maxx += a[u].tag;
  47. a[a[u].lc].tag += a[u].tag;
  48. a[a[u].rc].tag += a[u].tag;
  49. a[u].tag = 0;
  50. return ;
  51. }
  52. inline void build(int &u,int l,int r){
  53. if(!u) u = ++t;
  54. if(l == r){
  55. a[u].maxx = dis[l];
  56. a[u].pos = l;
  57. return ;
  58. }
  59. int mid = (l + r) >> 1;
  60. build(a[u].lc,l,mid);build(a[u].rc,mid + 1,r);
  61. pushup(u);
  62. }
  63. inline void updata(int u,int l,int r,int ll,int rr,LL w){
  64. if(ll > rr) return;
  65. if(l == ll && r == rr){
  66. a[u].maxx += w;
  67. a[u].tag += w;
  68. return ;
  69. }
  70. pushdown(u,l,r);
  71. int mid = (l + r) >> 1;
  72. if(rr <= mid) updata(a[u].lc,l,mid,ll,rr,w);
  73. else if(ll > mid) updata(a[u].rc,mid + 1,r,ll,rr,w);
  74. else{
  75. updata(a[u].lc,l,mid,ll,mid,w);
  76. updata(a[u].rc,mid + 1,r,mid + 1,rr,w);
  77. }
  78. pushup(u);
  79. }
  80. inline int query(){return a[root].pos;}
  81. }T;
  82. int main(){
  83. n = read();
  84. for(int i = 1;i <= n;++i) dis[i] = read();
  85. T.build(root,1,n);
  86. // cout << "GG" << endl;
  87. for(int i = 1;i <= n;++i){
  88. int x = T.query();
  89. an[x] = i;
  90. T.updata(root,1,n,x + 1,n,-i);
  91. T.updata(root,1,n,x,x,INF);
  92. }
  93. for(int i = 1;i <= n;++i) printf("%d ",an[i]);
  94. return 0;
  95. }

E

当时就硬是没想出来差分的技巧

首先每个位置可以取到的数肯定是

\([x - (w - len),x+(w -len)]\)这个区间的最大值

之后我们分两种情况讨论

首先

当\(len >= w -len\)时

这时候会长成这个样子

我们设\(d = w - len\)表示能够滑动的距离

对于一个位置\(x\)

首先,绿色部分是只能够从左向右取最大值\([x - d,x]\)

红色只能从右向左取最大值\([x,x + d]\)

中间部分呢?这一部分你会发现

这一部分其实可以和红色或者绿色任意一部分合起来算

这个时候注意不要把黄色部分重复计算就好

当\(len < w - len\)时

这个时候,中间的黄色部分的答案,就变成了序列中的最大值和\(0\)取max

因为中间部分是可以取到序列中的任意数

所以我们只需要维护区间最大值,这个东西随便搞搞吧

注意判断越界时要和\(0\)取max,表示可以不选

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<queue>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cctype>
  7. #include<vector>
  8. #include<deque>
  9. #include<ctime>
  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 = 1e6 + 3;
  17. const int INF = 2e9;
  18. int n,len,w;
  19. int f[21][N];
  20. LL ans[N];
  21. int lg[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 void pre(){
  35. for(int j = 1;(1 << j) <= len;++j){
  36. for(int i = 1;i + (1 << j) - 1 <= len;++i)
  37. f[j][i] = max(f[j - 1][i],f[j - 1][i + (1 << (j - 1))]);
  38. }
  39. }
  40. inline int work(int l,int r){
  41. int k = lg[r - l + 1];
  42. return max(f[k][l],f[k][r - (1 << k) + 1]);
  43. }
  44. inline int query(int l,int r){
  45. if(l < 1 || r > len) return max(0,work(max(1,l),min(len,r)));
  46. else return work(l,r);
  47. }
  48. int main(){
  49. lg[1] = 0;
  50. for(int i = 2;i <= 1000000;++i) lg[i] = lg[i >> 1] + 1;
  51. n = read(),w = read();
  52. for(int i = 1;i <= n;++i){
  53. len = read();
  54. for(int j = 1;j <= len;++j) f[0][j] = read();
  55. pre();
  56. for(int i = 1;i <= len;++i){
  57. int k = query(i,i + w - len);
  58. ans[i + w - len] += k;
  59. ans[i + w - len + 1] -= k;
  60. }
  61. for(int i = 1;i <= min(len,w - len);++i){
  62. int k = query(i - w + len,i);
  63. ans[i] += k;
  64. ans[i + 1] -= k;
  65. }
  66. if(len < w - len){
  67. int k = max(0,query(1,len));
  68. ans[len + 1] += k;
  69. ans[w - len + 1] -= k;
  70. }
  71. }
  72. for(int i = 1;i <= w;++i) {ans[i] += ans[i - 1];printf("%lld ",ans[i]);}
  73. return 0;
  74. }

F

神仙题解\(SOS DP\)

题目大意求\((i,j,j)i < j < k\)使得\(a_i | (a_j \&a_i)\)最大

\(n <= 10^6,a_i < 2^{21}\)

考虑从从后向前枚举\(i\)

从高位向低位贪心

设\(dp_x\)表示\(x\)设个二进制集合被多少数完全包含

每次对于一个\(a_i\)

从大到小枚举所有位

如果这个位\(j\)不是\(1\)同时满足当前贪心的结果\(x\),\(x | (1 << j)\)被超过两个数包含(保证\(\&\)完之后有这个数)就将这一位加入贪心的答案

更新完答案之后就把每一位包含\(a_i\)的加入

时间复杂度貌似有点爆炸

但是我们发现如果\(dp_x >=2\)那么直接return

所以每个位置最多被更新两次

均摊是\(2^{21}\)的复杂度

  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. #define LL long long
  10. #define pii pair<int,int>
  11. #define mk make_pair
  12. #define fi first
  13. #define se second
  14. using namespace std;
  15. const int N = 1e6 + 3;
  16. int a[N];
  17. int cnt[N << 2];
  18. int n;
  19. inline int read(){
  20. int v = 0,c = 1;char ch = getchar();
  21. while(!isdigit(ch)){
  22. if(ch == '-') c = -1;
  23. ch = getchar();
  24. }
  25. while(isdigit(ch)){
  26. v = v * 10 + ch - 48;
  27. ch = getchar();
  28. }
  29. return v * c;
  30. }
  31. int ans = 0;
  32. inline void ins(int x,int d){
  33. if(cnt[x] >= 2) return;
  34. if(d == -1){cnt[x]++;return;}
  35. ins(x,d - 1);
  36. if(x & (1 << d)) ins(x ^ (1 << d),d - 1);
  37. }
  38. inline int query(int x){
  39. int now = 0;
  40. for(int i = 20;i >= 0;--i) if(((x & (1 << i)) == 0) && cnt[now | (1 << i)] >= 2) now |= 1 << i;
  41. return now | x;
  42. }
  43. int main(){
  44. n = read();
  45. for(int i = 1;i <= n;++i) a[i] = read();
  46. for(int i = n;i >= 1;--i){
  47. if(i <= n - 2) ans = max(ans,query(a[i]));
  48. ins(a[i],20);
  49. }
  50. printf("%d\n",ans);
  51. return 0;
  52. }

CF1208的更多相关文章

  1. CF-1208 C.Magic Grid

    题目 大意:构造一个n行n列的矩阵,使得每一行,每一列的异或和都相等,n是4的倍数. 先看4*4的矩阵,我们很容易构造出符合要求的矩阵,比如 0    1    2    3 4    5    6  ...

  2. CF1208题解

    C \(\begin{aligned}\ 0 0 1 1\\ 0 0 1 1\\ 2 2 3 3\\ 2 2 3 3\\ \end{aligned}\)将每个四方格分别加上\(0,4,8,12\) D ...

  3. CF1208 Red Blue Tree

    题目链接 问题分析 这是蒟蒻第一道3500!不过话说luogu上两个题解的程序都是假的可还行(2019.11.1)-- 为了方便叙述,下面我们约定 : \([c]\) 的值为 \(1\) 当且仅当 \ ...

  4. cf1208 E Let Them Slide(差分+RMQ\单调队列)

    题意 如题目的图所示,每行都可以左右移动,但是数字不允许断开,且不许越界(宽度为w). 单独求每一列的最大的和为多少. 思路 对于每一列来说,在每一行上都有一个可以取到的区间, 所以,对于一列来说,答 ...

  5. cf1208 D Restore Permutation (二分+树状数组)

    题意 让你构造一个长度为n的序列,记为p1……pn,(这个序列是1~n的全排列的一种) 给你n个数,记为s1……sn,si的值为p1……pi-1中小于pi的数的和. 思路 显然,应该倒着来,也就是从p ...

随机推荐

  1. More Effective C++: 05技术(25-28)

    25:将constructor 和 non-member functions 虚化 所谓 virtual constructor是某种函数,视其输入可产生不同类型的对象.比如下面的代码: class ...

  2. Java练习 SDUT - 2669_2-2 Time类的定义

    2-2 Time类的定义 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 通过本题目的练习可以掌握类与对象的定义: 设计 ...

  3. select引起的服务端程序崩溃问题

    现象: 某个线上的服务最近频繁崩溃.该服务使用C++编写,是个网络服务端程序.作为TCP服务端,接收和转发客户端发来的消息,并给客户端发送消息.该服务跑在CentOS上,8G内存.线上环境中,与客户端 ...

  4. 破解fireworks_cs6、phoneshop_cs6、dreamweaver_cs6

    我的Adobe密码是绿尘枫加**0,首字母大写,在我的百度云盘有这三款软件的补丁,这三款软件安装和破解的方式都一样.先下载正常安装好正版软件>正常试用一遍之后,fireworks的补丁装错了文件 ...

  5. 从零学React Native之09可触摸组件

    可触摸组件有: TouchableHighlight,TouchableNativeFeedback,TouchableOpacity,TouchableWithoutFeedback 1. Touc ...

  6. python 布尔型(bool)

  7. hdu 3272 Mission Impossible

    Mission Impossible Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  8. day2_python之字符编码

    一 .计算机基础知识 二.文本编辑器存取文件的原理(nodepad++,pycharm,word) #1.打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放与内存中的, ...

  9. python selenium 处理悬浮窗口(baidu tj_more)

    python selenium 处理悬浮窗口 from selenium.webdriver.common.action_chains import ActionChainsActionChains( ...

  10. 性能改善后复杂SQL

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-/ ...