noi.ac #553 序列

【题目描述】

老虎和蒜头是好朋友。

众所周知,蒜头经常给老虎出一些题目,而老虎也常常被难倒,作为捧杯之王的老虎难免心有怨怼。今天,老虎发现了蒜头的一个序列 a​ 。虽然老虎不知道这个序列是用来做什么的,但老虎还是希望搞点破坏——他计划把序列 a​ 全部变成 0​ 。

然而,对蒜头的序列进行操作绝不是容易的事情。具体来说,老虎每次可以选择两个位置 i,j(i≠j) ,将 ai 和 aj 变为 ai⊕aj,其中 ⊕ 是异或操作。

然而,只将蒜头的一个序列变成 0 实在是不够解气。因此,老虎希望你能够对于 m 组询问 l,r ,告诉老虎对于该序列的一个子序列 al,al+1,…,ar,最少需要操作几次才能将该序列变为全 0 序列。

【输入格式】

输入的第一行包括两个正整数 n,m​ ,表示序列的长度和询问的次数。

接下来 m​ 行,每行两个正整数 li,ri​ ,表示一组询问。

【输出格式】

输出共 m​ 行,每行一个数,表示该组询问最少的操作次数。

【样例数据】

input
5 3
3 3 3 3 5
1 5
2 3
3 5
output
4
1
3

【数据范围】

对于 100% 的数据,0≤ai<230。

Subtask 1(20 分): 2≤n,m≤10

Subtask 2(30 分): 2≤n,m≤2000

Subtask 3(50 分): 2≤n,m≤2×105

时间限制: 2s

空间限制: 512MB

很显然,对于一段区间,如果有相同的数,那么一次可以消掉两个。如果两个数不同,那么两次就能消掉(它们两个碰两次),如果有单个的,需要两次才能消掉(一次和0,一次它们两个相消)。

很显然,我们只需要维护一段区间中相同的数的个数,和落单的数的个数,这个每次拓展一位是很好处理的。

所以上莫队就行了。QAQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,m,block,cur_ans,sum1;
int a[MAXN],b[MAXN],pos[MAXN],ans[MAXN],sum[MAXN];
struct Node{int id,l,r;}node[MAXN];
inline bool cmp(struct Node x,struct Node y)
    {return pos[x.l]<pos[y.l]||(pos[x.l]==pos[y.l]&&x.r<y.r);}
inline void ins(int x)
{
    if(!x) return;
    if(sum[x]%2==1)
    {
        if(sum1&1) cur_ans--,sum1=0;
        else cur_ans++,sum1=1;
    }
    else 
    {
        if(sum1&1) sum1=0;
        else cur_ans+=2,sum1=1;
    }
    sum[x]++;
}
inline void del(int x)
{
    if(!x) return;
    if(sum[x]%2==1)
    {
        if(sum1&1) cur_ans-=2,sum1=0;
        else sum1=1;
    }
    else
    {
        if(sum1&1) cur_ans--,sum1=0;
        else cur_ans++,sum1=1;
    }
    sum[x]--;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    block=(int)sqrt(1.0*n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    memcpy(b,a,sizeof(a));
    sort(&b[1],&b[n+1]);
    int k=unique(&b[1],&b[n+1])-b-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(&b[1],&b[k+1],a[i])-b;
    for(int i=1;i<=n;i++)
    {
        pos[i]=i/block;
        if(i%block) pos[i]++;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&node[i].l,&node[i].r);
        node[i].id=i;
    }
    sort(&node[1],&node[m+1],cmp);
    int l=1,r=0;
    for(int i=1;i<=m;i++)
    {
        // printf("%d %d\n",node[i].l,node[i].r);
        while(r<node[i].r) r++,ins(a[r]);
        while(l>node[i].l) l--,ins(a[l]);
        while(l<node[i].l) del(a[l]),l++;
        while(r>node[i].r) del(a[r]),r--;
        ans[node[i].id]=cur_ans;
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}
posted @ 2019-07-12 22:06  风浔凌  阅读(339)  评论(0编辑  收藏  举报