题目链接

离别

离线算法+线段树

容易发现当我们枚举右端点r时,符合条件的左端点是一段连续的区间

我们可以用队列来维护这个连续区间的左右端点

当枚举到端点\(i\)时,将下标\(i\)插入到队列\(q[a_i]\)中

如果元素大于k,队首+1即为左端点(注意要与之前的取max)

如果元素等于k,队首即为右端点

这样对每个右端点,就找到了符合条件的左端点

然后将询问离线,以右端点排序

对于每个右端点,将符合条件的左端点插入线段树中,同时查询答案

时间复杂度\(O(nlogn)\)

(注意要开long long,还有update 与 query 都要push_down)

代码

#include <bits/stdc++.h>
#define LL long long
#define int long long
#define ls(p) p << 1
#define rs(p) p << 1|1
using namespace std;
const int N = 3e5 + 101;
int tree[N * 4], laz[N * 4];
int a[N], b[N], tl[N], tr[N];
int n, q, k, ans[N];
struct node {int id, l;};
queue<int>que[N];
vector<node>ask[N]; void push_up(int p)
{
tree[p] = tree[ls(p)] + tree[rs(p)];
}
void push_down(int p,int l,int r)
{
int mid = (l + r) / 2;
tree[ls(p)] += (mid - l + 1) * laz[p];
tree[rs(p)] += (r - mid) * laz[p];
laz[ls(p)] += laz[p];
laz[rs(p)] += laz[p];
laz[p] = 0;
} void update(int p,int l,int r,int nl,int nr,int ad)
{
if(nl <= l && r <= nr)
{
laz[p] += ad;tree[p] += (r - l + 1) * ad;
return;
}
push_down(p,l,r);
int mid = (l + r) / 2;
if(nl <= mid) update(ls(p),l,mid,nl,nr,ad);
if(nr > mid) update(rs(p),mid + 1,r,nl,nr,ad);
push_up(p);
} int query(int p,int l,int r,int nl,int nr)
{
int ans = 0;
if(nl <= l && r <= nr) return tree[p];
push_down(p,l,r);
int mid = (l + r) / 2;
if(nl <= mid) ans += query(ls(p),l,mid,nl,nr);
if(nr > mid) ans += query(rs(p),mid + 1,r,nl,nr);
return ans;
}
signed main()
{
scanf("%lld%lld%lld",&n,&q,&k);
for(int i = 1;i <= n; i++)
scanf("%lld",&a[i]);
int L = 0,R = 0; // 对应的左区间符合条件的答案
for(int i = 1;i <= n; i++)
{
que[a[i]].push(i);
if(que[a[i]].size() > k)
L = max(L,que[a[i]].front()),que[a[i]].pop(); //更新左端点
if(que[a[i]].size() == k)
R = max(R,que[a[i]].front());
tl[i] = L + 1;tr[i] = R;
}
for(int i = 1;i <= q; i++)
{
int l, r;scanf("%lld%lld",&l,&r);
ask[r].push_back((node){i,l});
}
for(int i = 1;i <= n; i++)
{
if(tl[i] <= tr[i]) update(1,1,n,tl[i],tr[i],1);
for(int j = 0;j < ask[i].size(); j++)
ans[ask[i][j].id] = query(1,1,n,ask[i][j].l,i);
}
for(int i = 1;i <= q; i++) printf("%lld\n",ans[i]);
} /*
4 4 2
1 2 3 4
1 2
1 3
1 4
2 4
*/

最新文章

  1. JavaScript Timer实现动画效果
  2. swift:谈谈swift几种常见属性的区别
  3. LINUX各目录用处
  4. SecureCRT使用sz和rz命令进行文件的上传和下载
  5. mysql存储过程中的异常处理
  6. java函数substring()
  7. 基础学习day04---数组的操作
  8. Java生成excel导出文件(使用poi+JXL)
  9. 组织http请求
  10. CoreGraphics --- 翻转坐标系
  11. Ⅶ.AngularJS的点点滴滴-- 事件
  12. ScrollView与ListView合用(正确计算Listview的高度)的问题解决
  13. 高性能网络server--I/O复 select poll epoll_wait之间的差
  14. 【LeetCode】22. Generate Parentheses (I thought I know Python...)
  15. JSON, list, 前台显示
  16. iwebshop两表联查
  17. HDU - 1407 打表
  18. 关于MYCAT 读写分离,与只读事务的问题.
  19. 在Spring Boot中使用数据缓存
  20. 2018-2019-1 20189210 《Linux内核原理与分析》第三周作业

热门文章

  1. Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)复现
  2. 这几种实现线程的方法你一定要知道,月薪20k以上的面试都会问到
  3. Mac专用下载器Folx软件中有没有“下载速度控制”功能
  4. Spring5.0源码学习系列之Spring AOP简述
  5. 体育成绩统计/ Score
  6. dubbo起停之配置注解
  7. qsort的cmp函数理解
  8. 测试:ADB
  9. Django 的模板语法之过滤器
  10. SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂)