2020牛客多校(五) H

这道题我们发现固定一个端点,那么和他不同的或值答案就是不超过log个,因为就算每个只少一个0,那也只有20位

现在的问题是如何去重,采用的方法是对于每个右端点,用mp查找与他或起来的不同值,绑定一个三元组表示或值为u的键值对为i,j,这里我们可以覆盖掉一些被包含的点,因为不可能成为答案

之后继续去重,把包含的区间去除掉,采用的方法是排序。

之后就是个二维数点的模板,可以采用主席树来维护,这里抄了一下别人的板子

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson tr[rt].l
#define rson tr[rt].r
#define mid ((l+r)>>1)
#define x first
#define y second
typedef pair<int,int> pll;
typedef long long ll;
const int N=1e6+100;
const int mod=1e9+7;
struct node{int l,r,sum;}tr[N<<5];
int tot;
void build(int &rt,int l,int r){
    rt=++tot;
    if(l==r) 
        return;
    build(lson,l,mid);
    build(rson,mid+1,r);
}
void add(int &rt,int l,int r,int pre,int pos,int val){
    rt=++tot;tr[rt]=tr[pre];tr[rt].sum+=val;
    if(l==r) return;
    if(pos<=mid) add(lson,l,mid,tr[pre].l,pos,val);
    else add(rson,mid+1,r,tr[pre].r,pos,val);
}
int query(int rt,int l,int r,int pre,int ql,int qr){
    if(ql<=l&&r<=qr) return tr[rt].sum-tr[pre].sum;
    int ans=0;
    if(ql<=mid) ans+=query(lson,l,mid,tr[pre].l,ql,qr);
    if(mid<qr) ans+=query(rson,mid+1,r,tr[pre].r,ql,qr);
    return ans;
}
int a[N],root[N];
map<int,int> tmp,mp;
map<int,vector<pll>> po;
vector<int> add1[N],sub[N];
bool cmp(pll a,pll b){
    if(a.first==b.first){
        return a.second>b.second;
    }
    return a.first<b.first;
}
int main(){
    int n,m;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        tmp.clear();
        for(auto u:mp) tmp[a[i]&u.first]=u.second;
        tmp[a[i]]=i;
        mp=tmp;
        for(auto u:mp)
            po[u.first].push_back({u.second,i});
    }
    for(auto u:po){
        auto v=u.second;
        sort(v.begin(),v.end(),cmp);
        vector<pll> sta;
        int i;
        for(i=0;i<v.size();i++){
            if(i==0)
                sta.push_back(v[i]);
            if(v[i].second<=sta.back().second){
                sta.pop_back();
            }
            sta.push_back(v[i]);
        }
        int sz=sta.size();
        for(i=0;i<sz;i++){
            add1[sta[i].first].push_back(sta[i].second);
            if(i)
            sub[sta[i-1].first].push_back(sta[i].second);
        }
    }
    build(root[0],1,n);
    for(i=1;i<=n;i++){
        int pre=root[i-1];
        for(auto u:add1[i]) add(root[i],1,n,pre,u,1),pre=root[i];
        for(auto u:sub[i]) add(root[i],1,n,pre,u,-1),pre=root[i];
    }
    int q,las=0;scanf("%d",&q);
    while(q--){
        int l,r;scanf("%d%d",&l,&r);
        l=(l^las)%n+1;r=(r^las)%n+1;
        if(l>r) swap(l,r);
        printf("%d
",las=query(root[n],1,n,root[l-1],1,r));
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/13430658.html