题意:有一串数字 a[i] 和一个K 还有m个查询 x1 y1 x2 y2
求一共有多少对数u,v 满足 a[u]+a[v]==K u在区间x1 y1 v在区间x2 y2种
用容斥定理即可
ans= f(x1,y2) - f(x1,x2-1) - f(y1+1,y2) + f(y1+1,x2-1) 就是答案了
注意维护的方式也比较巧妙
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define CLR(A,v) memset(A,v,sizeof A) #define inf 0x3f3f3f3f #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 ////////////////////////////////////// const int N=3e4+5; struct node { int l,r,flag,id; }s[N<<2]; int anss[N],ans,L,R,cnt[N],n,a[N],K,m,x1,x2,y2,block,cnt1,yy;//我的cb上不能定义y1 不然疯狂报错??? bool judge(int x) { return x>=1&&x<=n; } void add(int x) { x=a[x]; cnt[x]++; if(judge(K-x))ans+=cnt[K-x]; } void del(int x) { x=a[x]; cnt[x]--; if(judge(K-x))ans-=cnt[K-x]; } bool cmp(node a,node b) { return (a.l/block)==(b.l/block)?a.r<b.r:a.l<b.l; } int main() { while(~RI(n)) { RI(K);rep(i,1,n)RI(a[i]);RI(m);cnt1=0; rep(i,1,m) { anss[i]=cnt[i]=0; RII(x1,yy);RII(x2,y2); s[++cnt1].flag=1, s[cnt1].l=x1,s[cnt1].r=y2,s[cnt1].id=i; s[++cnt1].flag=-1,s[cnt1].l=x1,s[cnt1].r=x2-1,s[cnt1].id=i; s[++cnt1].flag=-1,s[cnt1].l=yy+1,s[cnt1].r=y2,s[cnt1].id=i; s[++cnt1].flag=1, s[cnt1].l=yy+1,s[cnt1].r=x2-1,s[cnt1].id=i; } block=sqrt(n); sort(s+1,s+1+cnt1,cmp); L=1,R=0,ans=0; rep(i,1,cnt1) { int l=s[i].l,r=s[i].r; while(L<l)del(L++); while(L>l)add(--L); while(R<r)add(++R); while(R>r)del(R--); anss[s[i].id]+=s[i].flag*ans; } rep(i,1,m)printf("%d ",anss[i]); } return 0; }