您的位置:首页 > 其它

莫队算法 Codeforces617E XOR and Favorite Number

2016-01-31 21:18 253 查看
传送门:点击打开链接

题意:给n个数和一个k,有很多次查询,每次查询有l,r,求[l,r]有多少个子区间的xor之和等于k

思路:很明显是个裸莫队算法(原来在国外也烂大街

有几个要注意的地方,就是对于左端点操作的时候,实际上是操作L-1,以及vis和sum的更新顺序

还有就是记录数量的时候,vis数组至少要开109w,而不是100w,因为最后的异或可能把后面的0全部填满

区间的个数可能会爆int,所以答案要用LL存,一不小心就错了

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<LL, int>PII;

const int MX = 1e5 + 10;
const int MQ = 1e5 + 10;
const int MP = 2e6 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

LL ans[MX];
int n, unit, k, Qt;
int vis[MP], A[MX], B[MX];

struct Que {
int L, R, id;
bool operator<(const Que &b)const {
if(L / unit == b.L / unit) {
if(R == b.R) return L < b.L;
return R < b.R;
}
return L / unit < b.L / unit;
}
} Q[MQ];

void solve() {
LL sum = 0;
int L = 1, R = 0, c = 1;
vis[0] = 1;
while(c <= Qt) {
while(Q[c].L < L) {
L--;
sum += vis[k ^ B[L - 1]];
vis[B[L - 1]]++;
}
while(Q[c].R > R) {
R++;
sum += vis[k ^ B[R]];
vis[B[R]]++;
}
while(Q[c].L > L) {
vis[B[L - 1]]--;
sum -= vis[k ^ B[L - 1]];
L++;
}
while(Q[c].R < R) {
vis[B[R]]--;
sum -= vis[k ^ B[R]];
R--;
}
ans[Q[c++].id] = sum;
}
}

int main() {
//FIN;
scanf("%d%d%d", &n, &Qt, &k);
B[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
B[i] = B[i - 1] ^ A[i];
}
for(int i = 1; i <= Qt; i++) {
scanf("%d%d", &Q[i].L, &Q[i].R);
Q[i].id = i;
}
unit = sqrt(n + 0.5);
sort(Q + 1, Q + 1 + Qt);

solve();
for(int i = 1; i <= Qt; i++) {
printf("%I64d\n", ans[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: