首页 > 其他 > 详细

[莫队][离散化]luogu P3709 大爷的字符串题

时间:2019-08-20 10:18:24      阅读:99      评论:0      收藏:0      [点我收藏+]

https://www.luogu.org/problem/P3709

分析

从题目描述可以看出来出题人语文不行

理清题目描述后,其实是问在一个区间内取出一个严格上升数列,取完区间需要多少次

这个再思考一下,其实就是在问出现最多的数出现了多少次

由于值域1e9,我们考虑离散

由于可以离线的不带修区间操作,我们考虑莫队

离散后,times数组记录某数字出现了多少次,num数组记录有多少数字出现了i次

至于为什么涉及到答案时是O(1)的,因为当前答案失效后,它也只减少了一次出现次数啊,所以是原答案-1

 

技术分享图片
#include <iostream> 
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e5+10;
struct Query {
    int l,r,id;
}t[N];
int n,fn,m,fm;
int a[N],b[N],times[N],num[N],id[N],ans[N],lans;

bool CMP(Query a,Query b) {
    return id[a.l]<id[b.l]||id[a.l]==id[b.l]&&(((id[a.l]&1)^1)^(a.r<b.r));
}

void Solve(int x,bool type) {
    if (type) {
        num[times[x]]--;
        times[x]++;num[times[x]]++;
        lans=max(lans,times[x]);
    }
    else {
        num[times[x]]--;if (lans==times[x]&&num[times[x]]==0) lans--;
        times[x]--;num[times[x]]++;
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);fn=unique(b+1,b+n+1)-b-1;
    for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+fn+1,a[i])-b;
    for (int i=1;i<=m;i++) scanf("%d%d",&t[i].l,&t[i].r),t[i].id=i;
    fm=sqrt(m);
    for (int i=1;i<=m;i++) id[i]=i/fm+(i%fm>0);
    sort(t+1,t+m+1,CMP);
    num[0]=n;
    int l=1,r=1;Solve(a[1],1);
    for (int i=1;i<=m;i++) {
        while (r<t[i].r) Solve(a[++r],1);while (t[i].l<l) Solve(a[--l],1);
        while (l<t[i].l) Solve(a[l++],0);while (t[i].r<r) Solve(a[r--],0);
        ans[t[i].id]=lans;
    }
    for (int i=1;i<=m;i++) printf("%d\n",-ans[i]);
}
View Code

 

[莫队][离散化]luogu P3709 大爷的字符串题

原文:https://www.cnblogs.com/mastervan/p/11380841.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!