莫队模板

P2709 小B的询问 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:最最模板的一集.

//#pragma GCC optimize(2)       o2优化
//#pragma GCC optimize(3,"Ofast","inline")  o3优化
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"

int n,m,k,B;
int arr[50004],p[50004];
typedef struct Q{
    int l,r,idx;
}Q;
Q q[50004];
//bool cmp(Q a,Q b){     普通分块排序
//    if(a.l/B!=b.l/B) return a.l<b.l;
//    return a.r<b.r;
//}
bool cmp(Q a,Q b){   玄学奇偶性排序
    if (p[a.l] ^ p[b.l]) return a.l/B < b.l/B ;
    else{
        if (p[a.l] & 1) return a.r < b.r;
        else return a.r > b.r;
    }
}
int l=0,r=0,res=0,cnt[50004],ans[50004];
P2709 小B的询问
https://www.luogu.com.cn/problem/P2709
void solve(){
    cin>>n>>m>>k;
    B=sqrt(n);
    for(int i=1;i<=n;i++) cin>>arr[i];
    for(int i=1;i<=m;i++) cin>>q[i].l>>q[i].r,q[i].idx=i,p[q[i].l]=q[i].l/B,p[q[i].r]=q[i].r/B;
    sort(q+1,q+m+1,cmp);
    l=q[1].l+1,r=q[1].l;
    for(int i=1;i<=m;i++){
        while(l>q[i].l) {
            --l;
            int num=arr[l];
            if(num<=k) {
                res-=cnt[num]*cnt[num];
                cnt[num]++;
                res+=cnt[num]*cnt[num];
            }
        }
        while(r<q[i].r) {
            ++r;
            int num=arr[r];
            if(num<=k) {
                res-=cnt[num]*cnt[num];
                cnt[num]++;
                res+=cnt[num]*cnt[num];
            }
        }
        while(l<q[i].l) {
            int num=arr[l];
            if(num<=k){
                res-=cnt[num]*cnt[num];
                cnt[num]--;
                res+=cnt[num]*cnt[num];
            }
            l++;
        }
        while(r>q[i].r) {
            int num=arr[r];
            if(num<=k){
                res-=cnt[num]*cnt[num];
                cnt[num]--;
                res+=cnt[num]*cnt[num];
            }
            r--;
        }
        ans[q[i].idx]=res;
    }
    for(int i=1;i<=m;i++) cout<<ans[i]<<endl;
}

signed main() {
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

P1903 [国家集训队] 数颜色 / 维护队列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:带修莫队,多了操作和回退的操作.

//#pragma GCC optimize(2)       o2优化
//#pragma GCC optimize(3,"Ofast","inline")  o3优化
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"

int n,m,B;
int arr[200005],p[200005];
int ans[200005],cnt[1000006];
int idxR=0,idxQ=0;
typedef struct r{
    int p,c;
}r;
r R[200005];
typedef struct q{
    int l,r,tim,id;
}q;
bool cmp(q a,q b){   奇偶性排序
    if(p[a.l] ^ p[b.l]) return a.l<b.l;
    else if(p[a.r] ^ p[b.r]) return a.r<b.r; p[a.r] != p[b.r]  不是a.r!=b.r
    else return a.tim<b.tim;   时间排序
}
q Q[200005];
带修莫队
P1903 [国家集训队] 数颜色 / 维护队列
https://www.luogu.com.cn/problem/P1903
void solve(){
    cin>>n>>m;
    B=pow(n,0.666);
    for(int i=1;i<=n;i++) cin>>arr[i];
    for(int i=1;i<=m;i++){
        char op; cin>>op;
        int l,r; cin>>l>>r;
        if(op=='Q') {
            Q[++idxQ].l=l,Q[idxQ].r=r,Q[idxQ].tim=idxR,Q[idxQ].id=idxQ;
            p[Q[idxQ].l]=ceil(1.0*Q[idxQ].l/B),p[Q[idxQ].r]=ceil(1.0*Q[idxQ].r/B);
        }
        else R[++idxR].p=l,R[idxR].c=r;
    }
    sort(Q+1,Q+idxQ+1,cmp);
    int l=Q[1].l+1,r=Q[1].l,t=0,res=0;
    for(int i=1;i<=idxQ;i++){
        while(l>Q[i].l){  左扩展
            --l;
            cnt[arr[l]]++;
            if(cnt[arr[l]]==1) res++;
        }
        while(r<Q[i].r){   右扩展
            ++r;
            cnt[arr[r]]++;
            if(cnt[arr[r]]==1) res++;
        }
        while(l<Q[i].l){  左删除
            cnt[arr[l]]--;
            if(cnt[arr[l]]==0) res--;
            ++l;
        }
        while(r>Q[i].r){  右删除
            cnt[arr[r]]--;
            if(cnt[arr[r]]==0) res--;
            --r;
        }
        while(t<Q[i].tim){  进行操作
            int p0=R[++t].p;
            if(p0>=Q[i].l&&p0<=Q[i].r){  要在范围内才更新!!
                cnt[arr[p0]]--;
                if(cnt[arr[p0]]==0) res--;
                cnt[R[t].c]++;
                if(cnt[R[t].c]==1) res++;
            }
            swap(arr[p0],R[t].c);
        }
        while(t>Q[i].tim){  回退操作
            int p0=R[t].p;
            if(p0>=Q[i].l&&p0<=Q[i].r){  要在范围内才更新!!
                cnt[arr[p0]]--;
                if(cnt[arr[p0]]==0) res--;
                cnt[R[t].c]++;
                if(cnt[R[t].c]==1) res++;
            }
            swap(arr[p0],R[t].c);
            t--;
        }
        ans[Q[i].id]=res;
    }
    for(int i=1;i<=idxQ;i++) cout<<ans[i]<<endl;
}

signed main() {
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

Problem - H - Codeforces-Round974-Div3

思路:最普通的莫队板子.没想到出现在div3的最后一题。用随机数异或哈希也能过.

int n,m,k,B;
int arr[250004],p[250004];
typedef struct Q{
    int l,r,idx;
}Q;
Q q[250004];
//bool cmp(Q a,Q b){     普通分块排序
//    if(a.l/B!=b.l/B) return a.l<b.l;
//    return a.r<b.r;
//}
bool cmp(Q a,Q b){   玄学奇偶性排序
    if (p[a.l] ^ p[b.l]) return a.l/B < b.l/B ;
    else{
        if (p[a.l] & 1) return a.r < b.r;
        else return a.r > b.r;
    }
}
int l=0,r=0,cnt[1000006],ans[250004];
P2709 小B的询问
https://www.luogu.com.cn/problem/P2709
void solve(){
    cin>>n>>m;
    B=sqrt(n);
    for(int i=1;i<=n;i++) cin>>arr[i],cnt[arr[i]]=0;
    for(int i=1;i<=m;i++) cin>>q[i].l>>q[i].r,q[i].idx=i,p[q[i].l]=q[i].l/B,p[q[i].r]=q[i].r/B;
    sort(q+1,q+m+1,cmp);
    l=q[1].l+1,r=q[1].l;
    int cnt1=0;//
    for(int i=1;i<=m;i++){
        while(l>q[i].l) {
            --l;
            cnt[arr[l]]^=1;
            if(cnt[arr[l]]==1) cnt1++;
            else cnt1--;
        }
        while(r<q[i].r) {
            ++r;
            cnt[arr[r]]^=1;
            if(cnt[arr[r]]==1) cnt1++;
            else cnt1--;
        }
        while(l<q[i].l) {
            cnt[arr[l]]^=1;
            if(cnt[arr[l]]==1) cnt1++;
            else cnt1--;
            l++;
        }
        while(r>q[i].r) {
            cnt[arr[r]]^=1;
            if(cnt[arr[r]]==1) cnt1++;
            else cnt1--;
            r--;
        }
        ans[q[i].idx]=(cnt1==0);
    }
    for(int i=1;i<=m;i++){
        if(ans[i]==1) cout<<"YES\n";
        else cout<<"NO\n";
    }
}

F-小苯的回文询问_牛客周赛 Round 38 (nowcoder.com)

思路:最普通的板子,得o(1)维护变动.

int n,m,B;
int arr[100005],p[200005];
typedef struct Q{
    int l,r,idx;
}Q;
Q q[200005];
bool cmp(Q a,Q b){   玄学奇偶性排序
    if (p[a.l] ^ p[b.l]) return a.l/B < b.l/B ;
    else{
        if (p[a.l] & 1) return a.r < b.r;
        else return a.r > b.r;
    }
}
int l=0,r=0,ans[200005];
void solve(){     //牛客周赛Round38    //F  又是莫队
    cin>>n>>m;
    B=sqrt(n);
    unordered_map<int,int> ha;
    int num=0;
    for(int i=1;i<=n;i++) {
        cin>>arr[i];
        if(ha[arr[i]]==0) ha[arr[i]]=++num;  离散化
        arr[i]=ha[arr[i]];
    }
    for(int i=1;i<=m;i++) cin>>q[i].l>>q[i].r,q[i].idx=i,p[q[i].l]=q[i].l/B,p[q[i].r]=q[i].r/B;
    sort(q+1,q+m+1,cmp);
    l=q[1].l+1,r=q[1].l;
    int cnt[200005];
    int cntNex=0,cnt2=0,cnt3=0;
    for(int i=1;i<=m;i++){
        while(l>q[i].l){  //扩张
            --l;
            cnt[arr[l]]++;
            if(cnt[arr[l]]==2) cnt2++;
            if(cnt[arr[l]]==3) cnt3++;
            if(arr[l]==arr[l+1]) cntNex++;
        }
        while(r<q[i].r){  //扩张
            ++r;
            cnt[arr[r]]++;
            if(cnt[arr[r]]==2) cnt2++;
            if(cnt[arr[r]]==3) cnt3++;
            if(arr[r]==arr[r-1]) cntNex++;
        }
        while(l<q[i].l){ //收缩
            cnt[arr[l]]--;
            if(cnt[arr[l]]==1) cnt2--;
            if(cnt[arr[l]]==2) cnt3--;
            if(arr[l]==arr[l+1]) cntNex--;
            l++;
        }
        while(r>q[i].r){ //收缩
            cnt[arr[r]]--;
            if(cnt[arr[r]]==1) cnt2--;
            if(cnt[arr[r]]==2) cnt3--;
            if(arr[r]==arr[r-1]) cntNex--;
            r--;
        }
        if(cnt3||cnt2>cntNex) ans[q[i].idx]=1;
    }
    for(int i=1;i<=m;i++) ans[i]?cout<<"YES"<<endl:cout<<"NO"<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值