莫队算法

莫队算法是对暴力的一种优雅诠释,以根号n分块然后进行排序分类   (莫队很简单 ,但这个例题被我做炸了)

莫队先将给的数据分块,然后将每次询问的顺序记录下来  也就是node.id   最后再输出

不得不说  莫队这个操作直接优化根号n实在是太强

https://codeforces.com/problemset/problem/617/E

题目大意:求在每次询问中,区间内异或和等于3的组数

可能是对异或和接触比较少  ,一上来看到题就傻了,后来才想起来异或和的基操,在这里面都用到了

a[ i , j ] = a [ 0 , i ] ^ a [ 0 , j ] 

附上ac代码

#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=1<<20;
int n,m,k;
ll pos[maxn];            //pos是指分的哪一块
int a[maxn];             //数组a前缀和   记录前n项的异或和
ll Ans=0;
int L=1,R=0;
ll flag[maxn],ans[maxn];     //flag就是总和   ans是结果
struct node
{
    int l,r,id;
}Q[maxn];

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];
}
void add(int x)
{
    Ans+=flag[a[x]^k];   //   我死都想不出来qwq
    flag[a[x]]++;
}
void del(int x)
{
    flag[a[x]]--;    
    Ans-=flag[a[x]^k];         //注意顺序
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int sz=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i]^=a[i-1];
        pos[i]=i/sz;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&Q[i].l,&Q[i].r);
        Q[i].id=i;
    }
    flag[0]=1;
    sort(Q+1,Q+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        while(L<Q[i].l)
        {
            del(L-1);     //对于异或操作还是太不了解  看能不能补一补
            L++;
        }
        while(L>Q[i].l)
        {
            L--;         //
            add(L-1);
        }
        while(R<Q[i].r)
        {
            R++;
            add(R);
        }
        while(R>Q[i].r)
        {
            del(R);
            R--;
        }
        ans[Q[i].id]=Ans;
    }
    for(int i=1;i<=m;i++)
        printf("%I64d\n",ans[i]);
    return 0;
}

 https://vjudge.net/problem/SPOJ-DQUERY

模板题   记录所问区间中有多少种颜色

Example

Input
5
1 1 2 1 3
3
1 5
2 4
3 5

Output
3
2
3 
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=300010;
int cnt[1000010];

int R=0,L=1,Ans=0;
int a[maxn],ans[maxn],pos[maxn];
struct node
{
    int l,r,id;
}q[maxn];
bool cmp(node a,node b)
{
    if(pos[a.l]==pos[b.l])
        return a.r<b.r;
    return pos[a.l]<pos[b.l];
}

void del(int x)        //改这里
{
    cnt[a[x]]--;
    if(cnt[a[x]]==0)
        Ans--;

}
void add(ll x)          //改这里
{
    if(cnt[a[x]]==0)
        Ans++;
    cnt[a[x]]++;
}
void mo(int i)
{
    while(L>q[i].l)
    {
        add(--L);
    }
    while(L<q[i].l)
    {
        del(L++);
    }
    while(R>q[i].r)
    {
        del(R--);
    }
    while(R<q[i].r)
    {
        add(++R);
    }
    ans[q[i].id]=Ans;
}

int main()
{
    int n,t;
    scanf("%d",&n);
    int len=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%d%d",&q[i].l,&q[i].r);
        pos[i]=i/len;                //分块
        q[i].id=i;
    }
    sort(q+1,q+1+t,cmp);              //分块排序
    for(int i=1;i<=t;i++)
    {
        mo(i);
    }
    for(int i=1;i<=t;i++)
        printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2019-07-25 21:14  AAAzhuo  阅读(107)  评论(0)    收藏  举报