HDU 5213
题意:给出长度为n的序列a,和一个奇数K.
m次询问[l,r,u,v] l<=r<u<=v.问从[l,r],[u,v]两个区间中分别选一个数x,y.问满足x+y=k的(x,y)对数
n,m<=3e4. a[i]<=n.
记录两组询问区间中每个数的出现频率 增加一个数时容易知道它的贡献,莫队排序后离线一下.
[l,r,u,v] 每个询问有两个区间 不能直接排序? 所以把这两个不相关的区间拆成4个独立的区间 .f[l,r]为l,r内两数加为k的对数.
题意:给出长度为n的序列a,和一个奇数K.
m次询问[l,r,u,v] l<=r<u<=v.问从[l,r],[u,v]两个区间中分别选一个数x,y.问满足x+y=k的(x,y)对数
n,m<=3e4. a[i]<=n.
记录两组询问区间中每个数的出现频率 增加一个数时容易知道它的贡献,莫队排序后离线一下.
[l,r,u,v] 每个询问有两个区间 不能直接排序? 所以把这两个不相关的区间拆成4个独立的区间 .f[l,r]为l,r内两数加为k的对数.
res[l,r,u,v] = f[l,v] - f[l,u-1] - f[r+1,v] + f[r+1,u-1].
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e4+5,M=4*N;
struct node{
int l,r,id,sig;
}q[M];
int n,k,Q,res,tot,a[N],pos[N],fre[N],ans[N];
void init()
{
res=0,tot=0;
memset(fre,0,sizeof(fre));
int block=sqrt(n);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/block+1;
}
bool cmp(node a,node b)
{
if(pos[a.l]==pos[b.l])
return a.r<b.r;
return a.l<b.l;
}
void add(int p)
{
int x=a[p];
if(x>k)
return;
fre[x]++;
res+=fre[k-x];
}
void del(int p)
{
int x=a[p];
if(x>k)
return;
res-=fre[k-x];
fre[x]--;
}
void solve()
{
for(int i=1,l=1,r=0;i<=tot;i++)
{
for(;r<q[i].r;r++)
add(r+1);
for(;l>q[i].l;l--)
add(l-1);
for(;r>q[i].r;r--)
del(r);
for(;l<q[i].l;l++)
del(l);
ans[q[i].id]+=q[i].sig * res;
}
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
init();
scanf("%d",&Q);
int l,r,u,v;
for(int i=1;i<=Q;i++)
{
ans[i]=0;
scanf("%d%d%d%d",&l,&r,&u,&v);
q[++tot].l=l,q[tot].r=v,q[tot].id=i,q[tot].sig=1;
q[++tot].l=l,q[tot].r=u-1,q[tot].id=i,q[tot].sig=-1;
q[++tot].l=r+1,q[tot].r=v,q[tot].id=i,q[tot].sig=-1;
if(r+1<=u-1)
q[++tot].l=r+1,q[tot].r=u-1,q[tot].id=i,q[tot].sig=1;
}
sort(q+1,q+1+tot,cmp);
solve();
for(int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
}
return 0;
}