题目传送门:E - At Least One (atcoder.jp)

题意:

给定大小为N的两个数组A,B,求长度分别为1~M的满足以下条件的连续序列数量,条件为:

对于每个i(从1~N),Ai和Bi至少有一个包含于此序列之内。

思路:双指针 + 差分

容易知道,当序列[L, R]是满足条件的连续序列时,则左边界向左拓展,右边界向右拓展时,得到的新序列依旧满足条件。

那么我们枚举左边界L,然后移动右边界,使得其为满足条件的最小右边界(记为Rmin),则长度在[Rmin - L + 1, M - L + 1]之间的答案都增加1,可以用双指针+差分实现。

 

代码参考:

//Jakon; Two Pointers and Difference
#include <bits/stdc++.h>
using namespace std; const int N = 200010; int n, m, cnt[N], ans[N];
vector<int> v[N]; int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
int a, b;
scanf("%d%d", &a, &b);
v[a].push_back(i), v[b].push_back(i);
} int sum = 0;
for(int i = 1, j = 0; i <= m && j <= m; i++)
{
//以i为左边界,找到满足条件的最小右边界j
while(sum < n && j < m) {
++ j;
for(auto& idx : v[j]) {
++ cnt[idx];
if(cnt[idx] == 1) ++ sum;
}
}
//若区间[i, j]满足条件,则长度在[j-i+1, m-i+1]的答案都+1,即以i为左边界的所有可能情况都+1
if(sum == n && j <= m) {
++ ans[j - i + 1], -- ans[m - i + 2];
}
//左边界i要右移一位,于是先把原本i的贡献去掉
for(auto& idx : v[i]) {
-- cnt[idx];
if(cnt[idx] == 0) -- sum;
}
} for(int i = 1; i <= m; i++) cout << (ans[i] += ans[i - 1]) << " ";
cout << endl; return 0;
}

最新文章

  1. CentOS6.3 编译安装LAMP(4):编译安装 PHP5.2.17
  2. .NET工程师面试宝典
  3. C++ - 扩展欧几里德算法非递归实现
  4. IOS开发--数据持久化篇之文件存储(一)
  5. 深入了解line-height
  6. C# DataTable怎么合计字段
  7. C++ 虚函数与纯虚函数
  8. poj 1887 Testing the CATCHER_最长上升子序列
  9. SSH整合中为获取表单对象Action类实现的接口及拦截器配置
  10. java中String与StringBuffer拼接的区别
  11. TensorFlow之RNN:堆叠RNN、LSTM、GRU及双向LSTM
  12. list遍历时删除的坑
  13. HBase shell scan 过滤器用法总结
  14. ubuntu下绑定串口
  15. suList() 和 asList()
  16. luogu P1979 [NOIP2013] 华容道
  17. 部分手机(如三星)的Listview列表会自动加上黑线解决办法
  18. 【转】Android Camera 相机开发详解
  19. JQuery攻略(二) Jquery手册
  20. Python 网络请求模块 urllib 、requests

热门文章

  1. 使用BGP-blackhole解决IDC频繁遭受DDOS攻击困扰
  2. Map和WeakMap的方法和区别
  3. ApeForms | WinForm窗体UI美化库(Metro扁平风格)演示与安装
  4. drools动态增加、修改、删除规则
  5. kruskar重构树
  6. 基于.NetCore开发博客项目 StarBlog - (10) 图片瀑布流
  7. Node.js安装与环境配置
  8. CabloyJS v3.1.0支持集群及更多 &#127881;
  9. 3D还原货拉拉女孩身亡真相,这一环值得反思!
  10. numpy学习笔记 01