从上到下枚举上下底边,那么涉及两行的添加和删除。

首先预处理出对于每一列,每个位置添加和删除时,是否会对往下$k$个里出现这个颜色造成影响。

然后对于每种颜色维护一个长度为$m$的bitset,表示哪些列出现过该颜色。

那么每次修改时,找到前驱和后继,对这一行答案的影响是一段区间加,差分前缀和即可。

时间复杂度$O(\frac{nm^2}{64})$。

  1. #include<cstdio>
  2. typedef unsigned int U;
  3. const int N=3010,M=100010,BUF=72000000;
  4. char Buf[BUF],*buf=Buf;
  5. int n,m,K,lim,i,j,k,u,d,a[N][N],cnt[M],s[N],mx;long long ans;bool in[N][N],ou[N][N];
  6. U f[M][N/32+5];
  7. inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
  8. inline int max(int a,int b){return a>b?a:b;}
  9. inline int min(int a,int b){return a<b?a:b;}
  10. inline void add(U*f,int x){
  11. int y=x>>5,pre=-1,suf=-1;
  12. if(f[y]){
  13. int o=x&31;U z=f[y];
  14. for(int i=o-1;~i;i--)if(z>>i&1){pre=y<<5|i;break;}
  15. for(int i=o+1;i<32;i++)if(z>>i&1){suf=y<<5|i;break;}
  16. }
  17. if(pre<0)for(int i=y-1;~i;i--)if(f[i]){pre=i<<5|(31-__builtin_clz(f[i]));break;}
  18. if(suf<0)for(int i=y+1;i<=lim;i++)if(f[i]){suf=i<<5|__builtin_ctz(f[i]);break;}
  19. int l=max(pre+1,x-K+1),r=min(x,suf-K);
  20. if(l<=r)s[l]++,s[r+1]--;
  21. f[y]^=1U<<(x&31);
  22. }
  23. inline void del(U*f,int x){
  24. int y=x>>5,pre=-1,suf=-1;
  25. f[y]^=1U<<(x&31);
  26. if(f[y]){
  27. int o=x&31;U z=f[y];
  28. for(int i=o-1;~i;i--)if(z>>i&1){pre=y<<5|i;break;}
  29. for(int i=o+1;i<32;i++)if(z>>i&1){suf=y<<5|i;break;}
  30. }
  31. if(pre<0)for(int i=y-1;~i;i--)if(f[i]){pre=i<<5|(31-__builtin_clz(f[i]));break;}
  32. if(suf<0)for(int i=y+1;i<=lim;i++)if(f[i]){suf=i<<5|__builtin_ctz(f[i]);break;}
  33. int l=max(pre+1,x-K+1),r=min(x,suf-K);
  34. if(l<=r)s[l]--,s[r+1]++;
  35. }
  36. int main(){
  37. fread(Buf,1,BUF,stdin);read(n),read(m),read(K);
  38. for(i=1;i<=n;i++)for(j=1;j<=m;j++)read(a[i][j]);
  39. for(j=1;j<=m;j++){
  40. for(d=1;d<K;d++)if(!(cnt[a[d][j]]++))in[d][j]=1;
  41. for(u=0;d<=n;u++,d++){
  42. if(u)if(!(--cnt[a[u][j]]))ou[u][j]=1;
  43. if(!(cnt[a[d][j]]++))in[d][j]=1;
  44. }
  45. for(i=1;i<=n;i++)cnt[a[i][j]]=0;
  46. }
  47. lim=(m+1)>>5;
  48. for(i=1;i<M;i++){
  49. f[i][0]=1;
  50. f[i][(m+1)>>5]|=1U<<((m+1)&31);
  51. }
  52. for(d=1;d<K;d++)for(j=1;j<=m;j++)if(in[d][j])add(f[a[d][j]],j);
  53. for(u=0;d<=n;u++,d++){
  54. if(u)for(j=1;j<=m;j++)if(ou[u][j])del(f[a[u][j]],j);
  55. for(j=1;j<=m;j++)if(in[d][j])add(f[a[d][j]],j);
  56. for(j=1,k=0;j+K-1<=m;j++){
  57. k+=s[j];
  58. if(k>mx)mx=k;
  59. ans+=k;
  60. }
  61. }
  62. return printf("%d %lld",mx,ans),0;
  63. }

  

BZOJ5103 : [POI2018]Róznorodno的更多相关文章

  1. bzoj5103: [POI2018]Ró?norodno

    Description 给定一个n行m列的矩阵,请对于每个长宽均为k的连续子正方形,统计里面出现过的数值的种类数. Input 第一行包含三个正整数n,m,k(n,m<=3000,k<=m ...

  2. bzoj5100 [POI2018]Plan metra 构造

    5100: [POI2018]Plan metra Time Limit: 40 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 189  Sol ...

  3. [POI2018]Pionek

    [POI2018]Pionek 题目大意: 在无限大的二维平面的原点放置着一个棋子.你有\(n(n\le2\times10^5)\)条可用的移动指令,每条指令可以用一个二维整数向量表示.请你选取若干条 ...

  4. bzoj千题计划249:bzoj5100: [POI2018]Plan metra

    http://www.lydsy.com/JudgeOnline/problem.php?id=5100 1.找到d1[i]+dn[i] 最小的点,作为1到n链上的点 2.令链长为D,若abs(d1[ ...

  5. POI2018

    [BZOJ5099][POI2018]Pionek(极角排序+two pointers) 几个不会严谨证明的结论: 1.将所有向量按极角排序,则答案集合一定是连续的一段. 当答案方向确定时,则一个向量 ...

  6. 【BZOJ5102】[POI2018]Prawnicy 堆

    [BZOJ5102][POI2018]Prawnicy Description 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大 ...

  7. 【BZOJ5099】[POI2018]Pionek 几何+双指针

    [BZOJ5099][POI2018]Pionek Description 在无限大的二维平面的原点(0,0)放置着一个棋子.你有n条可用的移动指令,每条指令可以用一个二维整数向量表示.每条指令最多只 ...

  8. 【BZOJ5100】[POI2018]Plan metra 构造

    [BZOJ5100][POI2018]Plan metra Description 有一棵n个点的无根树,每条边有一个正整数权值,表示长度,定义两点距离为在树上的最短路径的长度. 已知2到n-1每个点 ...

  9. 【BZOJ5101】[POI2018]Powód 并查集

    [BZOJ5101][POI2018]Powód Description 在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无 ...

随机推荐

  1. maven依赖查找方法

    http://mvnrepository.com 1. 搜索依赖库         2. 选择合适版本 3. 复制配置 点击合适的版本进入,负责maven配置: <dependency> ...

  2. 步步为营-89-SQL语句(删除重复数据)

    1:删除重复数据 --第一步:先找到重复数据 select ProcInstID from record_errorlog group by ProcInstID having count(ProcI ...

  3. python爬虫点触验证码的识别思路(图片版)

  4. 使用python调用shell判断当前进程是否存在

    使用subprocess模块判断当前进程是否存在 #! /usr/bin/env python import subprocess res = subprocess.Popen(r'ps -ef |g ...

  5. C# 把ABCD转换成数字

    每倒题得选项可能是多选或者单选. public static string LetterTransformationNum(string answer, int type) { string num ...

  6. Give root password for maintenance(or type control -D to continue)

    2017-09-30 18:12:08 1:错误如图,本来开机准备用一下虚拟机,就出现一个这,为啥记录一下呢,因为网上好多不是很靠谱. 原因可能是之前关闭虚拟机的时候不小心出现异常了: 2:解决办法: ...

  7. 一脸懵逼学习HBase---基于HDFS实现的。(Hadoop的数据库,分布式的,大数据量的,随机的,实时的,非关系型数据库)

    1:HBase官网网址:http://hbase.apache.org/ 2:HBase表结构:建表时,不需要指定表中的字段,只需要指定若干个列族,插入数据时,列族中可以存储任意多个列(即KEY-VA ...

  8. MySQL主从备份配置实例

    转载自:https://www.cnblogs.com/ahaii/p/6307648.html MySQL主从备份配置实例 场景: 1.主服务器192.168.0.225.从服务器192.168.0 ...

  9. js 给定时间,如'2013-08-30',换算和今天的天数差

    由于项目中需要用到给定时间格式,如'2013-08-30',需要计算其和当前时间的间隔,需要算出间隔的时间,自己在网上搜索,并做了下简单的整理,总体思路分3步:1.将给定的时间和当前时间转换为毫秒 2 ...

  10. java运算符-算数、赋值、比较

    1.算术运算符 运算符是用来计算数据的符号.数据可以是常量,也可以是变量.被运算符操作的数我们称为操作数. 运算符 运算规则 范例 结果 + 正号 +3 3 + 加 2+3 5 + 连接字符串 “中” ...