P5268 [SNOI2017] 一个简单的询问

P5268 [SNOI2017] 一个简单的询问

题目描述

给你一个长度为 N 的序列 ai1iN,和 q 组询问,每组询问读入 l1,r1,l2,r2,需输出

x=0get(l1,r1,x)×get(l2,r2,x)

get(l,r,x) 表示计算区间 [l,r] 中,数字 x 出现了多少次。

数据范围

对于 100% 的数据,N,Q500001aiN1l1r1N1l2r2N

Solution:

首先我们不难发现我们可以用一个数组 cnt[pos][x] 来维护 [1,pos] 这个区间上 x 出现的次数,那么 get(l1,r1,x) 就可以用 cnt[r1][x]cnt[l11][x] 来刻画。所以我们可以把原式变形:

ans=(fr1fl1)×(fr2fl2)

=fr1fr2fr1fl2fl1fr2+fl1fl2

也就是说,我们只需要分别求出这四个值然后拼在一起就好了。

然后我们考虑如何维护这四个值:

假设现在有一个区间 [l,r] ,我们希望维护 flfr
当我们扩展区间至 [l,r+1] 时,答案会增加 cnt[l][ar+1] .但是如果这样开 cnt 的话空间复杂度会达到 n2 我们是不能接受的。但是我们发现,我们只关心 l,r 两个点的 cnt 所以我们可以动态维护两个桶 cntl,cntr 表示区间 [1,l],[1,r] 内的某种的颜色个数。对于左端点的扩展也是类似的,这里不过多赘述。

Code:

#include<bits/stdc++.h>
#define ll long long
const int N=5e4+5;
using namespace std;
int a[N],b[N],cntl[N],cntr[N],blc[N];
ll ans[N];
int n,m,S,tot;
int l,r;
ll tmp;
inline void move_l(int x)
{
if(x==1){cntl[a[++l]]++;tmp+=cntr[a[l]];}
else {cntl[a[l]]--;tmp-=cntr[a[l--]];}
}
inline void move_r(int x)
{
if(x==1){cntr[a[++r]]++;tmp+=cntl[a[r]];}
else {cntr[a[r]]--;tmp-=cntl[a[r--]];}
}
struct task{
int l,r,id,k;
bool operator <(const task &t)const{
return blc[l]==blc[t.l] ? (blc[l]&1 ? r<t.r : t.r<r) : l<t.l;
}
}t[N<<2];
void work()
{
cin>>n;S=sqrt(N);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);b[i]=a[i];
blc[i]=i/S;
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+1+n,a[i])-b;
}
cin>>m;
for(int i=1,l,r,L,R;i<=m;i++)
{
scanf("%d%d%d%d",&l,&r,&L,&R);
l--,L--;
t[++tot]={r,R,i,1};
t[++tot]={r,L,i,-1};
t[++tot]={l,R,i,-1};
t[++tot]={l,L,i,1};
}
for(int i=1;i<=tot;i++)if(t[i].l>t[i].r)swap(t[i].l,t[i].r);
sort(t+1,t+1+tot);
for(int i=1;i<=tot;i++)
{
while(t[i].l<l)move_l(-1);
while(l<t[i].l)move_l(1);
while(r<t[i].r)move_r(1);
while(t[i].r<r)move_r(-1);
ans[t[i].id]+=tmp*t[i].k;
}
for(int i=1;i<=m;i++)
{
printf("%lld\n",ans[i]);
}
}
int main()
{
//freopen("P5268.in","r",stdin);freopen("P5268.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示