题目链接:https://cn.vjudge.net/problem/HDU-5213
题意:从两个区间中各拿一个数,和为k的选法
题解:容斥一下即为:sum[l, v] - sum[l, u-1] - sum[r+1, v] + sum[r+1, u-1] sum[l, r] 表示从[l,r]中选择两个数和为k的选法, 剩下的就莫队分块解决一下就可以了
#include<bits/stdc++.h>
using namespace std;
const int N=30010;
int CM;
struct node{
int id;
int l,r;
int val;
bool operator <(const node &x)const
{
if(l/CM != x.l/CM) return l/CM < x.l/CM;
else return r<x.r;
}
}q[N*4];
int n,k,m;
int a[N],len;
int ans[N],num[N*2];
void add(int l,int r,int val,int id)
{
len++;
q[len].l=l;
q[len].r=r;
q[len].val=val;
q[len].id=id;
}
int main()
{
int l1,l2,r1,r2;
int l,r,res;
while(~scanf("%d",&n))
{
CM=(int)sqrt(n);
scanf("%d",&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
scanf("%d",&m);
len=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
add(l1,r2,1,i);
if(l1<=l2-1) add(l1,l2-1,-1,i);
if(r2>=r1+1) add(r1+1,r2,-1,i);
if(l2-1>=r1+1) add(r1+1,l2-1,1,i);
ans[i]=0;
}
sort(q+1,q+1+len);
for(int i=1,j=1;j<=len;i++)
{
l=q[j].l+1,r=q[j].l;
res=0;
for(int k=0;k<=n*2;k++)num[k]=0;
for(;j<=len && j<i*CM;j++)
{
while(l<q[j].l)
{
res-=num[max(0,k-a[l])];
num[a[l]]--;
l++;
}
while(l>q[j].l)
{
l--;
num[a[l]]++;
res+=num[max(0,k-a[l])];
}
while(r<q[j].r)
{
r++;
num[a[r]]++;
res+=num[max(0,k-a[r])];
}
while(r>q[j].r)
{
res-=num[max(0,k-a[r])];
num[a[r]]--;
r--;
}
// cout<<res<<" "<<q[j].l<<" "<<q[j].r<<endl;
ans[q[j].id]+=res*q[j].val;
}
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}