7GOJ 25 collection [分块][莫队]

4 篇文章 0 订阅
3 篇文章 0 订阅

原题就是BZOJ4241
XGG出的原题。。。我用莫队+分块暴力,结果subtaskGG了,改了一下块的大小, O(n)>O(nlogn) ,就AC了?GG垃圾卡莫队题。

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int N = 200010;
using namespace std;
long long n,m,block_size,belong[N],LM[N],RM[N];
vector<long long>G[N];
long long val[N],ans[N],size[N],num[N],block[N],like[N],temp[N],base[N],tot[N],sum[N];
struct query{
    long long l,r,id;
}q[N];
inline void read(long long &res){
    static char ch;long long flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
inline bool cmp(const query &a,const query &b){
    if(belong[a.l]==belong[b.l]){
        if(belong[a.l]%2==1)return a.r<b.r;
        else return a.r>b.r;
    }else return belong[a.l]<belong[b.l];
}
int main(){
    read(n),read(m);
    block_size=sqrt(n*(double)log(n*1.0)/log(2.0));//无解了,就一个块大小就能卡死我?
    for(register long long x,i=1;i<=n;++i)
        read(x),like[i]=temp[i]=x,belong[i]=(i-1)/block_size;
    sort(temp+1,temp+n+1);
    for(register long long i=1;i<=n;++i)
        base[i]=lower_bound(temp+1,temp+n+1,like[i])-temp,val[i]=like[i]*++size[base[i]];
    sort(val+1,val+n+1);
    for(register long long i=1;i<=n;++i)
        G[base[i]].push_back(lower_bound(val+1,val+n+1,like[i]*++num[base[i]])-val);
    for(register long long i=1;i<=m;++i)read(q[i].l),read(q[i].r),q[i].id=i;
    sort(q+1,q+m+1,cmp);
    for(register long long i=1;i<=n;++i)
        belong[i]=(i-1)/block_size+1;
    for(register long long i=1;i<=belong[n];++i)
        LM[i]=(i-1)*block_size+1,RM[i]=min(n,i*block_size);
    for(register long long i=1,L=1,R=0;i<=m;++i){
        while(R<q[i].r){
            R++;
            sum[belong[G[base[R]][block[base[R]]]]]++;
            tot[G[base[R]][block[base[R]]]]++;
            block[base[R]]++;
        }
        while(L>q[i].l){
            L--;
            sum[belong[G[base[L]][block[base[L]]]]]++;
            tot[G[base[L]][block[base[L]]]]++;
            block[base[L]]++;
        }
        while(L<q[i].l){
            block[base[L]]--;
            sum[belong[G[base[L]][block[base[L]]]]]--;
            tot[G[base[L]][block[base[L]]]]--;
            L++;
        }
        while(R>q[i].r){
            block[base[R]]--;
            sum[belong[G[base[R]][block[base[R]]]]]--;
            tot[G[base[R]][block[base[R]]]]--;
            R--;
        }
        for(register long long j=belong[n];j>=0;j--)
            if(sum[j])for(register long long k=RM[j];k>=LM[j];k--)
                if(tot[k]){
                    ans[q[i].id]=val[k];goto LMY;
                }
        LMY:;
    }
    for(register long long i=1;i<=m;++i)cout<<ans[i]<<endl;
    return 0;
}

安利一下neither_nor大佬的回滚莫队%%%
那么回滚莫队是什么?不知道。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值