(来源: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]\) 之间的数分别有多少。

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

// Author:A weak man named EricQian
// expect : 100 pts
#include<bits/stdc++.h>
using namespace std;
#define infll 0x7f7f7f7f7f7f7f7f
#define inf 0x3f3f3f3f
#define Maxn 500005
#define Maxm 7
typedef long long ll;
inline int rd()
{
int x=0;
char ch,t=0;
while(!isdigit(ch = getchar())) t|=ch=='-';
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return x=t?-x:x;
}
int n,m,tot;
int val[Maxn],num[Maxn];
int hea[Maxn],nex[Maxn<<1],ver[Maxn<<1];
struct TREE { ll minn,laz,cnt[Maxm]; }tree[Maxn<<2];
ll ans;
inline void add(int x,int y){ ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot; }
inline void pushup(int p)
{
int x=p<<1,y=p<<1|1,tmp;
if(tree[x].minn>tree[y].minn) swap(x,y);
tree[p].minn=tree[x].minn;
for(int i=0;i<m;i++) tree[p].cnt[i]=tree[x].cnt[i];
tmp=tree[y].minn-tree[x].minn;
for(int i=tmp;i<m;i++) tree[p].cnt[i]+=tree[y].cnt[i-tmp];
}
inline void pushdown(int p)
{
tree[p<<1].laz+=tree[p].laz,tree[p<<1].minn+=tree[p].laz;
tree[p<<1|1].laz+=tree[p].laz,tree[p<<1|1].minn+=tree[p].laz;
tree[p].laz=0;
}
void build(int p,int nl,int nr)
{
if(nl==nr) { tree[p].minn=tree[p].cnt[0]=1; return; }
int mid=(nl+nr)>>1;
build(p<<1,nl,mid),build(p<<1|1,mid+1,nr);
pushup(p);
}
void add(int p,int nl,int nr,int l,int r,int k)
{
if(nl>=l && nr<=r) { tree[p].minn+=k,tree[p].laz+=k; return; }
pushdown(p);
int mid=(nl+nr)>>1;
if(mid>=l) add(p<<1,nl,mid,l,r,k);
if(mid<r) add(p<<1|1,mid+1,nr,l,r,k);
pushup(p);
}
int main()
{
n=rd(),m=rd();
for(int i=1;i<=n;i++) val[i]=rd(),num[val[i]]=i;
for(int i=1,x,y;i<n;i++) x=rd(),y=rd(),add(x,y),add(y,x);
build(1,1,n);
for(int r=1;r<=n;r++)
{
if(r!=1) add(1,1,n,1,r-1,1);
for(int i=hea[num[r]];i;i=nex[i])
if(val[ver[i]]<val[num[r]])
add(1,1,n,1,val[ver[i]],-1);
for(int i=0;i<m;i++) ans+=tree[1].cnt[i];
ans-=(n-r);
}
printf("%lld\n",ans);
return 0;
}

【做题记录】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. 【OI】蛇形填数题的深入探究

    题目:在 n×n 方阵里填入 1,2,...n×n, 要求蛇形填数.例如,n=4 时方阵为: 10  11  12  1 9    16  13  2 8    15  14  3 7     6  ...

  2. 后台开发 3个题目 array_chunk, 100块钱找零钱(动态规划 dynamic programming), 双向循环链表 llist 删除节点

    1. array_chunk 实现 http://php.net/manual/en/function.array-chunk.php <?php function my_array_chunk ...

  3. tomcat 跨域的配置

    * 允许所有跨域  E:\apache-tomcat-7.0.81\conf\web.xml  <filter> <filter-name>CorsFilter</fil ...

  4. P3703-[SDOI2017]树点涂色【LCT,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P3703 题目大意 \(n\)个点的一棵树开始所有点有不同的颜色,\(m\)次操作 将根节点到\(x\)节点的路径上 ...

  5. NOI.AC#2139-选择【斜率优化dp,树状数组】

    正题 题目链接:http://noi.ac/problem/2139 题目大意 给出\(n\)个数字的序列\(a_i\).然后选出一个不降子序列最大化子序列的\(a_i\)和减去没有任何一个数被选中的 ...

  6. Java MD5和SHA256等常用加密算法

    前言 我们在做java项目开发的时候,在前后端接口分离模式下,接口信息需要加密处理,做签名认证,还有在用户登录信息密码等也都需要数据加密.信息加密是现在几乎所有项目都需要用到的技术,身份认证.单点登陆 ...

  7. 基于 Ubuntu 21.04 BPF 开发环境全攻略

    本文地址:https://www.ebpf.top/post/ubuntu_2104_bpf_env 1. 系统安装 1.1 Vagrant Vagrant 是一款用于构建及配置虚拟开发环境的软件,基 ...

  8. C语言实现简易计算器(可作加减乘除)

    C语言实现简易计算器(加减乘除) 计算器作为课设项目,已完成答辩,先将代码和思路(注释中)上传一篇博客 已增添.修改.整理至无错且可正常运行 虽使用了栈,但初学者可在初步了解栈和结构语法后理解代码 # ...

  9. 从单体迈向 Serverless 的避坑指南

    作者 | 不瞋 导读:用户需求和云的发展两条线推动了云原生技术的兴起.发展和大规模应用.本文将主要讨论什么是云原生应用,构成云原生应用的要素是什么,什么是 Serverless 计算,以及 Serve ...

  10. 题解 Children Trips

    题目传送门 Description 给出一个大小为 \(n\) 的边权全为 \(1,2\) 的带权树,有 \(q\) 此查询,每次给出 \(u,v,p\) ,问 \(u\to v\) 每次可以最多走边 ...