zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    mirco新建proto流程
    Ubuntu默认防火墙安装、启用、配置、端口、查看状态相关信息
    Rails核心组件
    Ruby中文乱码问题
    python str转dict
    SQLserver AwaysOn日志文件过大,处理办法
    MySQL的一些小细节
    mysql删除表中重复值
    可恶的自增长标识符
    reset slave all更彻底
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11178671.html
Copyright © 2011-2022 走看看