数据结构题(莫队算法)

数据结构题

https://ac.nowcoder.com/acm/problem/25835

数据结构题

题目:

问在区间[l,r]和[l1,r1]内x的出现次数的乘积是多少?

题解:

莫队算法的模板题
关于莫队算法你可以参考这个
我这里简单的说说我对莫队的理解:
莫队是一个优雅的暴力,就是将原本复杂度不能过的程序进行优化,莫队是通过分块来实现
如果暴力做这个题,查询区间[l,r]内x的数量我们可能就从头开始搜查,按照题目给的数据来搜查,但其实我们可以这样优化,比如题目给的查询区间[3,4],[2,4],[1,5],我们可以先查询[1,5],然后顺势查询[2,4],最后[3,4],而非从头开始,这样就省了不少时间。那如何实现这个?我们可以对整体进行分块,然后按照所分的快进行排序,尽可能实现查询区间时省时省力,最后再输出答案
至于为什么要分块排序呢?可以看看莫队算法的讲解
很显然这是一个离线算法,且适合查询量很大的情况
代码如下

代码:

#include<bits/stdc++.h>
#define forn(i,a,b) for(ll i=a;i<=b;i++)
#define INF 0x3f3f3f3f
using namespace std;

#define ll long long
const ll N =100*1000+10;
const ll mod = 20180623;
ll n,m;
ll a[N],ans[N*2],num[N],pos[N];
struct node{
    ll L,R,x,id;
}t[N*2];

bool cmp(node a,node b){
    if(pos[a.L]==pos[b.L])
        return a.R<b.R;
    else return pos[a.L]<pos[b.L];
}

ll L=1,R=0;
void solve(node p){
     while(p.L>L){
        num[a[L]]--;
        L++;
    }
    while(p.R>R){
        R++;
        num[a[R]]++;
    }
    while(p.L<L){
        L--;
        num[a[L]]++;
    }
    while(p.R<R){
        num[a[R]]--;
        R--;
    }
}

int main(){
    scanf("%lld %lld",&n,&m);
    memset(num,0,sizeof(num));
    ll block=sqrt(n);
    for(ll i=1;i<=n;i++){
        scanf("%lld",a+i);
        pos[i]=i/block;
    }

    for(ll i=1;i<=m;i++){
        ll l1,r1,l2,r2,x;
        scanf("%lld%lld%lld%lld%lld",&l1,&r1,&l2,&r2,&x);
        if(l1>r1)swap(l1,r1);
        if(l2>r2)swap(l2,r2);
        t[i].L=l1;
        t[i].R=r1;
        t[i].id=i;
        t[i].x=x;
        t[i+m].L=l2;
        t[i+m].R=r2;
        t[i+m].id=i+m;
        t[i+m].x=x;
    }

    sort(t+1,t+1+2*m,cmp);
    memset(num,0,sizeof(num));

    for(ll i=1;i<=2*m;i++){
        solve(t[i]);
        ans[t[i].id]=num[t[i].x];
    }

    for(ll i=1;i<=m;i++)
        printf("%lld\n%lld\n%lld\n",ans[i]%mod,ans[i+m]%mod,(ans[i]%mod*ans[i+m])%mod);

    return 0;
}
全部评论

相关推荐

自学java狠狠赚一...:骗你点star的,港卵公司,记得把star收回去
点赞 评论 收藏
分享
05-11 11:48
河南大学 Java
程序员牛肉:我是26届的双非。目前有两段实习经历,大三上去的美团,现在来字节了,做的是国际电商的营销业务。希望我的经历对你有用。 1.好好做你的CSDN,最好是直接转微信公众号。因为这本质上是一个很好的展示自己技术热情的证据。我当时也是烂大街项目(网盘+鱼皮的一个项目)+零实习去面试美团,但是当时我的CSDN阅读量超百万,微信公众号阅读量40万。面试的时候面试官就告诉我说觉得我对技术挺有激情的。可以看看我主页的美团面试面经。 因此花点时间好好做这个知识分享,最好是单拉出来搞一个板块。各大公司都极其看中知识落地的能力。 可以看看我的简历对于博客的描述。这个帖子里面有:https://www.nowcoder.com/discuss/745348200596324352?sourceSSR=users 2.实习经历有一些东西删除了,目前看来你的产出其实很少。有些内容其实很扯淡,最好不要保留。有一些点你可能觉得很牛逼,但是面试官眼里是减分的。 你还能负责数据库表的设计?这个公司得垃圾成啥样子,才能让一个实习生介入数据库表的设计,不要写这种东西。 一个公司的财务审批系统应该是很稳定的吧?为什么你去了才有RBAC权限设计?那这个公司之前是怎么处理权限分离的?这些东西看着都有点扯淡了。 还有就是使用Redis实现轻量级的消息队列?那为什么这一块不使用专业的MQ呢?为什么要使用redis,这些一定要清楚, 就目前看来,其实你的这个实习技术还不错。不要太焦虑。就是有一些内容有点虚了。可以考虑从PR中再投一点产出
投递美团等公司9个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务