[TK] 颜色
1.[TK] 矩阵取数游戏<简单版> hzoi-tg-906-22.[TK] 一心净士 hzoj-tg-937-23.[TK] 盖房子 hzoi-tg#2624.[TK] 三角蛋糕 hzoi-tg#2615.[TK] 选课 hzoj-tg#2796.[TK] 三色二叉树 hzoi-tg#282 存图方法7.[TK] HH的项链 离线树状数组解法8.[TK] 理想的正方形9.[TK] Blocks 单调栈10.[TK] 送礼物11.[TK] Terrible Prime12.[TK] BLO13.[TK] Rudolf and Subway ( CodeForces #933 div.3 - G )14.[TK] Bulls And Cows S
15.[TK] 颜色
16.[Tkey] 与非17.[TK] CF1526B I Hate 111118.[TK] 寻宝游戏19.[CL-22] 异或和之和20.联训题单 / 集训杂题纪要21.[At_dp_w] Intervals & [At_dp_x] Tower22.CF2023D - Many Games23.[NOI2021] 轻重边24.[CSP-S 2024] 染色谴责这道题发明在线莫队的人,简直就是异端,还好我给在线莫队卡了,支持正义制裁
题意简述
给定序列,设
表示 在 内的出现次数,对给定 求 . (强制在线)
解题思路
既然强制在线了,用不了莫队,那么为什么不用分块做呢.
首先不想分块,先想这题怎么求. 如果我们要求
不过我们这样做有一个小问题,就是三维数组太大,而序列长度也大,会炸,只能处理范围小一点的数据. 所以这个时候分块登场了. 我们可以利用这样的思想拆开区间,来求解整块的数据,剩下的打暴力,最后再把全部子区间答案加一下就好了.
但是两边打暴力也挺慢的,因为我们有不少元素需要处理,会显得效率很低. 所以我们考虑怎么快速计算
接下来考虑怎么在预处理部分把
对于
对于
代码实现
#include<bits/stdc++.h>
using namespace std;
int a[50001],sum[55][20001],//hou many j in fore i area
ans[55][55][20001],//how many [1,k] ans (sqre) from i to j
n,m,q,len,
l[50001],r[50001],
locate[50001],
tot[20001];
void prework(){
len=pow(n,0.666);
l[1]=1;
//work out the location
for(int i=1;i<=n;++i){
locate[i]=i/len+(i%len!=0);
if(i%len==0){
l[locate[i]+1]=i+1;
r[locate[i]]=i;
}
}
//work out the sum : sum[i][j]=sum[i-1][j]+ amount of area i.
for(int i=1;i<=locate[n];++i){
for(int j=1;j<=m;++j){
sum[i][j]=sum[i-1][j];
}
for(int j=l[i];j<=r[i];++j){
sum[i][a[j]]++;
}
}
//work out the ans : ans[i][j][k]=ans[i][j-1][k]+the number of amount k of area j.
//because ans is after sqre, so when add a number, ans from x^2 to (x+1)^2, which need to add 2x+1.
//so tot[] actually store amount of k before each add.
for(int i=1;i<=locate[n];++i){
for(int j=i;j<=locate[n];++j){
for(int k=1;k<=m;++k){
ans[i][j][k]=ans[i][j-1][k];
}
for(int k=l[j];k<=r[j];++k){
ans[i][j][a[k]]+=tot[a[k]]*2+1;
tot[a[k]]++;
}
}
for(int j=l[i];j<=n;++j){
tot[a[j]]&=0;
}
}
for(int i=1;i<=locate[n];++i){
for(int j=i;j<=locate[n];++j){
for(int k=1;k<=m;++k){
ans[i][j][k]+=ans[i][j][k-1];
}
}
}
}
int ask(int nl,int nr,int na,int nb){
//first solve whole area, using ans we worked out : [na,nb] = [1,nb]-[1,na-1]
int res=ans[locate[nl]+1][locate[nr]-1][nb]-ans[locate[nl]+1][locate[nr]-1][na-1];
//work out the other part, the same as we work out the ans
//1.when nl,nr in same area (avoid adding a area two times)
if(locate[nl]==locate[nr]){
for(int i=nl;i<=nr;++i){
if(a[i]>=na&&a[i]<=nb){
res+=tot[a[i]]*2+1;
tot[a[i]]++;
}
}
for(int i=nl;i<=nr;++i){
tot[a[i]]=0;
}
return res;
}
//2.else : left and right
for(int i=nl;i<=r[locate[nl]];++i){
if(a[i]<na||a[i]>nb){
continue;
}
if(!tot[a[i]]){
tot[a[i]]=sum[locate[nr]-1][a[i]]-sum[locate[nl]][a[i]];
}
res+=tot[a[i]]*2+1;
tot[a[i]]++;
}
for(int i=l[locate[nr]];i<=nr;++i){
if(a[i]<na||a[i]>nb){
continue;
}
if(!tot[a[i]]){
tot[a[i]]=sum[locate[nr]-1][a[i]]-sum[locate[nl]][a[i]];
}
res+=tot[a[i]]*2+1;
tot[a[i]]++;
}
//clear tot[]
for(int i=nl;i<=r[locate[nl]];++i){
tot[a[i]]&=0;
}
for(int i=l[locate[nr]];i<=nr;++i){
tot[a[i]]&=0;
}
return res;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
prework();
int o,p,y,u,last=0;
while(q --> 0){
scanf("%d%d%d%d",&o,&p,&y,&u);
o^=last;
p^=last;
y^=last;
u^=last;
last=ask(o,p,y,u);
printf("%d\n",last);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!