zoukankan      html  css  js  c++  java
  • Codeforces 617E:XOR and Favorite Number(莫队算法)

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

    题意:给出n个数,q个询问区间,问这个区间里面有多少个区间[i,j]可以使得ai^ai+1^...^aj = k。

    思路:根据xor的性质,可以处理出前缀异或和sum[],那么要使结果等于k,就是sum[i-1]^sum[j] == k,即sum[j]^k == sum[i-1],那么用一个数组cnt[]存储对于每一个sum[]的数量。然后用莫队算法做。莫队算法是一种离线处理区间问题的算法,在我看来是将询问通过分块排序成一个可以暴力处理的序列,让暴力的复杂度尽量的低。只有O(n*sqrt(n))的复杂度。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 #include <string>
     7 #include <iostream>
     8 #include <stack>
     9 #include <map>
    10 #include <queue>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 #define N 100010
    15 #define INF 0x3f3f3f3f
    16 struct node {
    17     int l, r, id;
    18     LL ans;
    19 } q[N*10];
    20 int sum[N], kuai, k;
    21 LL cnt[N*20];
    22 
    23 bool cmp1(const node &a, const node &b) {
    24     if(a.l / kuai != b.l / kuai) return a.l / kuai < b.l / kuai; // 根据块的编号排序
    25     return a.r < b.r; // 块内按照r值排序
    26 }
    27 
    28 bool cmp2(const node &a, const node &b) {
    29     return a.id < b.id;
    30 }
    31 
    32 int main()
    33 {
    34     int n, m, num, L, R;
    35     LL s = 0;
    36     scanf("%d%d%d", &n, &m, &k);
    37     for(int i = 1; i <= n; i++) {
    38         scanf("%d", &num); sum[i] = sum[i-1] ^ num;
    39     }
    40     for(int i = 1; i <= m; i++) {
    41         scanf("%d%d", &q[i].l, &q[i].r);
    42         q[i].id = i; q[i].l--;
    43     }
    44     kuai = sqrt(n);
    45     sort(q + 1, q + 1 + m, cmp1);
    46     L = 1; R = 0;
    47     for(int i = 1; i <= m; i++) {
    48         int l = q[i].l, r = q[i].r;
    49         while(L < l) {
    50             cnt[sum[L]]--;
    51             s -= cnt[sum[L]^k];
    52             L++;
    53         }
    54         while(L > l) {
    55             L--;
    56             s += cnt[sum[L]^k];
    57             cnt[sum[L]]++;
    58         }
    59         while(R < r) {
    60             R++;
    61             s += cnt[sum[R]^k];
    62             cnt[sum[R]]++;
    63         }
    64         while(R > r) {
    65             cnt[sum[R]]--;
    66             s -= cnt[sum[R]^k];
    67             R--;
    68         }
    69         q[i].ans = s;
    70     }
    71     sort(q + 1, q + 1 + m, cmp2);
    72     for(int i = 1; i <= m; i++) printf("%lld
    ", q[i].ans);
    73     return 0;
    74 }
  • 相关阅读:
    母版页和相对路径
    回发或回调参数无效
    ASPNETPAGER的使用方法
    关于ID的取法
    JS获取屏幕,浏览器,网页高度宽度
    form配置问题
    checkedListBox
    html标签的赋值与取值
    如何将前台线程改为后台线程
    在线程委托中实现参数的传递
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6279577.html
Copyright © 2011-2022 走看看