莫队(板子)

根据所求更改 add,del,answer就好

#include <bits/stdc++.h>
using namespace std;
typedef long  long  ll;
#define bug(x) cout<<#x<<" == "<<x<<endl;
const int maxn = 3e3+5;
ll mod = 1e6+7;
///const ll int INF=0x3f;
int a[maxn] = { 0 };
int block = 1;
inline int belong(int x)///也可以直接利用一个数组预处理下
{
    return (x-1)/block+1;
    ///x属于哪一块
}

int ans = 0;///当前区间有多少个元素
int cnt[100005] = { 0 };///目前区间的每个元素的个数统计

struct node
{
    int l,r;
    int id;
    bool operator <(node a)
    {
        if(belong(l)==belong(a.l))
        {
            return r<a.r;///属于同一块时 按右端点从小到大排序
        }
        else
        {
            return l<a.l;
        }
    }
}pp[maxn];
string answer[maxn];///最后要输出的答案
inline void add(int pos)
{
    cnt[ a[pos] ]++;
    if(cnt[ a[pos] ]==1)
        ans++;
}
inline void del(int pos)
{
    cnt[ a[pos] ]--;
    if(cnt[ a[pos] ]==0)
        ans--;
}
int main()
{
    int n,p;
    scanf("%d %d",&n,&p);
    int gs = (int)sqrt(n*1.0)+1;
    block = ceil(n/gs);

    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=p;i++)
    {
        scanf("%d %d", &pp[i].l,&pp[i].r);
        pp[i].id = i;
    }
    sort(pp+1,pp+1+p);
    int l=1,r=0;
    ///初始区间 是0
    for(int i=1;i<=p;i++)
    {
        int nl=pp[i].l;
        int nr=pp[i].r;
        ///下一个区间
        while(nl<l)
        {
            l--;
            add(l);
        }
        while(r<nr)
        {
            r++;
            add(r);
        }///扩大区间
        while(nl>l)
        {
            del(l);
            l++;
        }
        while(r>nr)
        {
            del(r);
            r--;
        }///缩小区间
        if( ans == (nr-nl+1) )
        answer[ pp[i].id ]="Yes\n";
        else
        answer[ pp[i].id ]="No\n";
    }
    for(int i=1;i<=p;i++)
        cout<<answer[i];
}

异或思想的运用很不错
链接;https://www.luogu.com.cn/problem/P4462

#include <bits/stdc++.h>
using namespace std;
typedef long  long  ll;
#define bug(x) cout<<#x<<" == "<<x<<endl;
const int maxn = 5e5+5;
ll mod = 1e6+7;
///const ll int INF=0x3f;
int a[maxn] = { 0 };
int block = 1;
inline int belong(int x)///也可以直接利用一个数组预处理下
{
    return (x-1)/block+1;
    ///x属于哪一块
}
ll ans = 0;
ll cnt[maxn] = { 0 };///每种颜色的袜子的个数的统计
ll answer[maxn] = { 0 };
struct node
{
    int l,r;
    int id;
    bool operator <(node a)
    {
        if(belong(l)==belong(a.l))
        {
            return r<a.r;///属于同一块时 按右端点从小到大排序
        }
        else
        {
            return l<a.l;
        }
    }
}pp[maxn];
int k;
inline void add(int pos)
{
    cnt[ a[pos] ]++;
    ans += cnt[ a[pos]^k ];///(a^b)^b = a;-> (a^k)^a = k;

}
inline void del(int pos)
{
    ans -= cnt[ a[pos]^k ];
    cnt[ a[pos] ]--;
}
int main()
{
    int n,p;
    scanf("%d %d %d", &n, &p, &k);
    int gs = (int)sqrt(n*1.0)+1;
    block = ceil(n/gs);

    for(int i=1;i<=n;i++)
    {
          scanf("%d",&a[i]);
          a[i] = a[i-1]^a[i];///转换为在区间[l,r]有多少对数异或为k
          ///a[l] ^ a[r]=(a[1]^a[2]^...^a[l])^(a[1]^a[2]^...^a[l])^(a[l+1]^a[l+2]^...^a[r])
          ///=(a[l+1]^a[l+2]^...^a[r])
    }
    for(int i=1;i<=p;i++)
    {
        scanf("%d %d", &pp[i].l,&pp[i].r);
        pp[i].id = i;
        pp[i].l--;
        ///a[i]记录的是从1~i的前缀异或
        ///所以区间[l,r]转化为的前缀异或区间应该是[l-1,r];
    }
    sort(pp+1,pp+1+p);
    int l=1,r=0;
    ///初始区间 是0
    for(int i=1;i<=p;i++)
    {
        int nl=pp[i].l;
        int nr=pp[i].r;
        ///下一个区间
        while(nl<l)
        {
            l--;
            add(l);
        }
        while(r<nr)
        {
            r++;
            add(r);
        }///扩大区间
        while(nl>l)
        {
            del(l);
            l++;
        }
        while(r>nr)
        {
            del(r);
            r--;
        }///缩小区间
        answer[ pp[i].id ] = ans;
    }
    for(int i=1;i<=p;i++)
    {
        printf("%lld\n",answer[i]);
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值