颜色
题目描述
给定一个长度为 \(N\) 的颜色序列 \(C\),对于该序列中的任意一个元素,都有 \(1\leq Ci \leq M\)。对于一种颜色 \(ColorK\) 来说,区间 \([L,R]\) 内的权值定义为这种颜色在该区间中出现的次数的平方,即区间 \([L,R]\) 内中满足等于 \(ColorK\) 的元素个数的平方。
接下来给出 \(Q\) 个询问,询问区间 \([L,R]\) 内颜色 \([a,b]\) 的权值总和。
输入格式
第 \(1\) 行三个整数 \(N,M,Q\)。
分别代表序列长度,颜色总数和询问总数。
第 \(2\) 行 \(N\) 个整数,代表序列。
第 \(3\) 行到第 \(Q+2\) 行,每行 \(4\) 个整数 \(l,r,a,b\)。记上一次计算出的答案为 \(Lans\)。那么实际的 \(l,r,a,b\) 为给出 \(l,r,a,b xor\) 上 \(Lans\)。第一个询问的时候 \(Lans=0\)。
输出格式
总共 \(Q\) 行,对于每一个询问,输出权值总和。
样例 #1
样例输入 #1
4 2 3
1 1 2 2
1 4 1 2
10 11 9 10
3 0 0 0
样例输出 #1
8
2
0
提示
\(1 \leq N,Q \leq 50000,M \leq 20000\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
int n, m, q, block;
int c[5211314], pos[5211314];
int pre[102][102][13140 * 2], sum[102][13140 * 2];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f *= -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch - '0');
ch = getchar();
}
return x * f;
}
inline void Pretreatment() {
for (int k = 1; k <= 20001; ++ k) {
for(int i = 1; i <= pos[n]; ++ i) {
sum[i][k] += sum[i - 1][k];
//sum[i][k]表示前i个块有几个k
}
}
for (int i = 1; i <= pos[n]; ++ i) {
for (int j = i; j <= pos[n]; ++ j) {
for(int k = 1; k <= 20001; ++ k) {
pre[i][j][k] = pow((sum[j][k] - sum[i - 1][k]), 2) + pre[i][j][k - 1];
//pre[i][j][k]表示i到j的块中1到k的权值总和
}
}
}
return;
}
inline int Ask(int lift, int right, int minn, int maxn) {
int l = pos[lift], r = pos[right], nowans = 0, temp[20001] = {};
if (l == r) {
for (int i = lift; i <= right; ++ i) {
if (c[i] >= minn && c[i] <= maxn) {
//注意判断
nowans = nowans + 2 * temp[c[i]] * 1 + 1 * 1;
//(a+b)^2 = a^2 + 2*a*b + b^2 其中temp[c[i]]是a,新加的1是b
//下一次的a要加1
temp[c[i]] += 1;
}
}
return nowans;
}
else {
nowans = nowans + (pre[l + 1][r - 1][maxn] - pre[l + 1][r - 1][minn - 1]);
for (int i = lift; i <= l * block; ++ i) {
if (c[i] < minn || c[i] > maxn) continue;
if (temp[c[i]] == 0) {
temp[c[i]] = sum[r - 1][c[i]] - sum[l][c[i]];
}
nowans = nowans + 2 * temp[c[i]] * 1 + 1 * 1;
temp[c[i]] ++;
}
for (int i = (r - 1) * block + 1; i <= right; ++ i) {
if (c[i] < minn|| c[i] > maxn) continue;
if (temp[c[i]] == 0) {
temp[c[i]] = sum[r - 1][c[i]] - sum[l][c[i]];
}
nowans = nowans + 2 * temp[c[i]] * 1 + 1 * 1;
temp[c[i]] ++;
}
return nowans;
}
}
int main() {
n = read();
m = read();
q = read();
block = 1000;
for (int i = 1; i <= n; ++ i) {
c[i] = read();
pos[i] = (i - 1) / block + 1;
sum[pos[i]][c[i]] ++;
}
Pretreatment();
int ans = 0;
for (int i = 1, l, r, a, b; i <= q; ++ i) {
l = read(), r = read();
a = read(), b = read();
l ^= ans, r ^= ans, a ^= ans, b ^= ans;
if (l > r) swap(l, r);
if (a > b) swap(a, b);
ans = Ask(l, r, a, b);
printf("%d\n",ans);
}
return 0;
}
标签:ch,颜色,temp,int,sum,leq,include
From: https://www.cnblogs.com/jueqingfeng/p/17442594.html