颜色

颜色

题目描述

给定一个长度为 N 的颜色序列 C,对于该序列中的任意一个元素,都有 1CiM。对于一种颜色 ColorK 来说,区间 [L,R] 内的权值定义为这种颜色在该区间中出现的次数的平方,即区间 [L,R] 内中满足等于 ColorK 的元素个数的平方。

接下来给出 Q 个询问,询问区间 [L,R] 内颜色 [a,b] 的权值总和。

输入格式

1 行三个整数 N,M,Q
分别代表序列长度,颜色总数和询问总数。

2N 个整数,代表序列。

3 行到第 Q+2 行,每行 4 个整数 l,r,a,b。记上一次计算出的答案为 Lans。那么实际的 l,r,a,b 为给出 l,r,a,bxorLans。第一个询问的时候 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

提示

1N,Q50000,M20000

#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;
}
posted @   觉清风  阅读(64)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示