zoukankan      html  css  js  c++  java
  • Codeforces 617E XOR and Favorite Number莫队

    http://codeforces.com/contest/617/problem/E

    题意:给出q个查询,每次询问区间内连续异或值为k的有几种情况。

    思路:没有区间修改,而且扩展端点,减小端点在前缀和的处理下都是O(n)的,使用莫队算法,每次移动区间时,注意计数是否先减.

    /** @Date    : 2016-12-09-19.31
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version :
      */
    #include<bits/stdc++.h>
    #define LL long long
    #define PII pair
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    
    struct sion
    {
        int l, r;
        int id;
    }s[N];
    
    LL a[N];
    LL cnt[N*100];
    int blc[N];
    LL res[N];
    
    int cmp(sion a, sion b)
    {
        if(blc[a.l] == blc[b.l])
            return a.r < b.r;
        return a.l < b.l;
    }
    
    int main()
    {
        int n, q, k;
        cin >> n >> q >> k;
        a[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld", a + i);
            a[i] = a[i] ^ a[i-1];
        }
        int dlt = sqrt(n);
        for(int i = 1; i <= n; i++)
        {
            blc[i] = (i - 1)/dlt + 1;
        }
    
        for(int i = 1; i <= q; i++)
        {
            scanf("%d%d", &s[i].l, &s[i].r);
            s[i].id = i;
        }
        sort(s + 1, s + 1 + q, cmp);
        MMF(cnt);
        cnt[0] = 1;
        LL ans = 0;
        int l = 0, r = 0;//前缀和的关系l初始为0
        for(int i = 1; i <= q; i++)
        {
            while(l > s[i].l - 1)//一定要注意边界问题
                l--, ans += cnt[k ^ a[l]], cnt[a[l]]++;//扩增区间先增加下标
            while(r < s[i].r)
                r++, ans += cnt[k ^ a[r]], cnt[a[r]]++;
            while(l < s[i].l - 1)
                cnt[a[l]]--,ans -= cnt[k ^ a[l]], l++;//缩小区间,由于前缀和的关系,先计数减1
            while(r > s[i].r)
                cnt[a[r]]--,ans -= cnt[k ^ a[r]] , r--;
            res[s[i].id] = ans;
    
    
        }
        for(int i = 1; i <= q; i++)
            printf("%lld
    ", res[i]);
        return 0;
    }
    
    
  • 相关阅读:
    简单复利计算java板
    弹出提示框的方式——java
    实验一 命令解释程序
    简单复利计算c语言实现
    操作系统
    jsp 页面和 jsp标记
    对it行业的一些看法
    又穷自动机的构造
    复利计算——结对编程2.0
    汉堡包
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/6151770.html
Copyright © 2011-2022 走看看