(来源:XJ高质量原创题)

原题地址

弱化版:CF526F Pudding Monsters

弱化版

题意:\(n\times n\) 的棋盘上有 \(n\) 颗棋子,每行每列都有且仅有一颗棋子,求出有多少个 \(k\times k\) 的子棋盘也满足每行每列只有一颗棋子。

将棋盘的 \(x\) 轴看作上一题中每个点的下标,\(y\) 轴看作这个点的权值。

其实就是树退化为了链,而 \(m=1\) 的情况。

题意

给定一棵树,每一个点有一个权值 \(a_i\) ,\(\{a\}\) 构成一个排列。

询问有多少个点集 \(S={u_1,u_2,\dots,u_k}(1\le j\le n)\) 满足这些点构成联通块不超过 \(m\) 个,且 \(\max_{1\le i\le k}\{a_{u_{i}}\}-\min_{1\le i\le k}\{a_{u_{i}}\}+1=k\) 。

\(n\le 10^5,m\le 7\)

题解

考虑枚举值域的右端点 \(r\),考虑加入这个右端点时,对与 \([1,r-1]\) 中的最短点的联通块个数的变化。

先假设假设这个点与其他无边相连,那么联通块数加 \(1\) 。

对于每一条与点集中的点相连的边 \((num(r),ver)\) ,都会使左端点在 \([1,val(ver)]\) 中的联通块数量 \(-1\) (\(num(x)\) 表示权值为 \(x\) 的点的编号)。

之后我们就将题意简化为:

  • 区间加上一个数

  • 求出整个数列中 \(\le m\) 的数有多少个

  • 保证 \(a[1]=1\)

考虑到 \(m\) 比较小,猜测答案复杂度为 \(O(nm\log n)\) 。

我们将加减操作同普通的线段树操作,主要改变 \(\text{pushup}\) 操作。

在线段树的每一个节点 \([l,r]\) 上维护:

  • \(minn\) : 表示在 \([l,r]\) 区间上数的最小值。

  • \(cnt[7]\) : 表示这段区间内值域在 \([minn,minn+6]\) 之间的数分别有多少。

之后根据两个子区间的最小值就可以愉快地转移啦!!

  1. // Author:A weak man named EricQian
  2. // expect : 100 pts
  3. #include<bits/stdc++.h>
  4. using namespace std;
  5. #define infll 0x7f7f7f7f7f7f7f7f
  6. #define inf 0x3f3f3f3f
  7. #define Maxn 500005
  8. #define Maxm 7
  9. typedef long long ll;
  10. inline int rd()
  11. {
  12. int x=0;
  13. char ch,t=0;
  14. while(!isdigit(ch = getchar())) t|=ch=='-';
  15. while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
  16. return x=t?-x:x;
  17. }
  18. int n,m,tot;
  19. int val[Maxn],num[Maxn];
  20. int hea[Maxn],nex[Maxn<<1],ver[Maxn<<1];
  21. struct TREE { ll minn,laz,cnt[Maxm]; }tree[Maxn<<2];
  22. ll ans;
  23. inline void add(int x,int y){ ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot; }
  24. inline void pushup(int p)
  25. {
  26. int x=p<<1,y=p<<1|1,tmp;
  27. if(tree[x].minn>tree[y].minn) swap(x,y);
  28. tree[p].minn=tree[x].minn;
  29. for(int i=0;i<m;i++) tree[p].cnt[i]=tree[x].cnt[i];
  30. tmp=tree[y].minn-tree[x].minn;
  31. for(int i=tmp;i<m;i++) tree[p].cnt[i]+=tree[y].cnt[i-tmp];
  32. }
  33. inline void pushdown(int p)
  34. {
  35. tree[p<<1].laz+=tree[p].laz,tree[p<<1].minn+=tree[p].laz;
  36. tree[p<<1|1].laz+=tree[p].laz,tree[p<<1|1].minn+=tree[p].laz;
  37. tree[p].laz=0;
  38. }
  39. void build(int p,int nl,int nr)
  40. {
  41. if(nl==nr) { tree[p].minn=tree[p].cnt[0]=1; return; }
  42. int mid=(nl+nr)>>1;
  43. build(p<<1,nl,mid),build(p<<1|1,mid+1,nr);
  44. pushup(p);
  45. }
  46. void add(int p,int nl,int nr,int l,int r,int k)
  47. {
  48. if(nl>=l && nr<=r) { tree[p].minn+=k,tree[p].laz+=k; return; }
  49. pushdown(p);
  50. int mid=(nl+nr)>>1;
  51. if(mid>=l) add(p<<1,nl,mid,l,r,k);
  52. if(mid<r) add(p<<1|1,mid+1,nr,l,r,k);
  53. pushup(p);
  54. }
  55. int main()
  56. {
  57. n=rd(),m=rd();
  58. for(int i=1;i<=n;i++) val[i]=rd(),num[val[i]]=i;
  59. for(int i=1,x,y;i<n;i++) x=rd(),y=rd(),add(x,y),add(y,x);
  60. build(1,1,n);
  61. for(int r=1;r<=n;r++)
  62. {
  63. if(r!=1) add(1,1,n,1,r-1,1);
  64. for(int i=hea[num[r]];i;i=nex[i])
  65. if(val[ver[i]]<val[num[r]])
  66. add(1,1,n,1,val[ver[i]],-1);
  67. for(int i=0;i<m;i++) ans+=tree[1].cnt[i];
  68. ans-=(n-r);
  69. }
  70. printf("%lld\n",ans);
  71. return 0;
  72. }

【做题记录】max-min+1=len 区间计数的更多相关文章

  1. 退役II次后做题记录

    退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...

  2. FJOI2017前做题记录

    FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...

  3. Sam做题记录

    Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...

  4. 退役IV次后做题记录

    退役IV次后做题记录 我啥都不会了.... AGC023 D 如果所有的楼房都在\(S\)同一边可以直接得出答案. 否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车 ...

  5. 退役III次后做题记录(扯淡)

    退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...

  6. BJOI做题记录

    BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...

  7. UOJ 做题记录

    UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...

  8. project euler做题记录

    ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{a ...

  9. AtCoder,Codeforces做题记录

    AGC024(5.20) 总结:猜结论,“可行即最优” B: 给定一个n的排列,每次可以将一个数移到开头或结尾,求变成1,2,...,n所需的最小步数. 找到一个最长的i,i+1,...,j满足在排列 ...

随机推荐

  1. MySQL查询之内连接,外连接查询场景的区别与不同

    前言 我在写sql查询的时候,用的最多的就是where条件查询,这种查询也叫内连查询inner join,当然还有外连查询outer join,左外连接,右外连接查询,常用在多对多关系中,那他们区别和 ...

  2. C语言学习笔记---3.字符串格式化输入输出

    1.C语言字符串 字符串(character string)是一个或多个字符的序列,例如:"Zing went the strings of my heart!" C语言没有专门用 ...

  3. HCNP Routing&Switching之IS-IS路由渗透和开销

    前文我们了解了IS-IS邻居建立过程.LSDB同步.拓扑计算和路由的形成:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15265698.html:今天我们来聊 ...

  4. idea鼠标双击.log日志文件无法打开

    发现只要再mybatis-config.xml的起别名中加<package name="xxx"/>,就会导致Reader entry: ����   1 n乱码,而R ...

  5. 微信小程序函数间传递url的参数丢失问题

    可以使用encodeURIComponent():函数可把字符串作为 URI 组件进行编码. 可以使用decodeURIComponent():函数可把字符串作为 URI 组件进行解码.  

  6. Python - 生成requirement.text 文件

    前言 该篇操作笔记摘自小菠萝 Python项目中,一般都会有一个 requirements.txt 文件 这个文件主要是用于记录当前项目下的所有依赖包及其精确的版本号,以方便在一个新环境下更快的进行部 ...

  7. 如何使用jemeter进行性能测试

    下载链接:http://jmeter.apache.org/download_jmeter.cgi 一:如何使用jemeter进行压测 1)稳定性测试就需要长时间运行,其运行时间1天.2天.一周等 2 ...

  8. YbtOJ#903-染色方案【拉格朗日插值,NTT,分治】

    正题 题目链接:https://www.ybtoj.com.cn/contest/115/problem/3 题目大意 两个长度为\(n+1\)的序列\(a,b\) \(a_i\)表示涂了\(i\)个 ...

  9. Sentry 监控 - 全栈开发人员的分布式跟踪 101 系列教程(第一部分)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  10. BurpSuite 功能概览

    简介 写作思想:相比较具体介绍某个功能的用法.会更加侧重于介绍 Burp 提供哪些功能.这样好处是在比较复杂的测试场景,如果Burp 刚好提供对应的功能,就不用花费精力造轮子了. 而需要掌握具体操作方 ...