HDU 5213 Lucky [莫队+容斥]

来源:互联网 发布:union c语言 编辑:程序博客网 时间:2024/06/06 14:12

题意:N个数,M个询问,每个询问给出两个区间,问从两个区间内各取一个数加起来和为K的方案数。

范围: N,M<=3W

解法: 3W考虑根号N解法,发现单个区间可以莫队,两个区间内各取可以容斥求。

代码:

#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<iostream>#include<stdlib.h>#include<set>#include<map>#include<queue>#include<vector>#include<bitset>#pragma comment(linker, "/STACK:1024000000,1024000000")template <class T>bool scanff(T &ret){ //Faster Input    char c; int sgn; T bit=0.1;    if(c=getchar(),c==EOF) return 0;    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    if(c==' '||c=='\n'){ ret*=sgn; return 1; }    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;    ret*=sgn;    return 1;}#define inf 1073741823#define llinf 4611686018427387903LL#define PI acos(-1.0)#define lth (th<<1)#define rth (th<<1|1)#define rep(i,a,b) for(int i=a;i<=b;i++)#define drep(i,a,b) for(int i=a;i>=b;i--)#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)#define mem(x,val) memset(x,val,sizeof(x))#define mkp(a,b) make_pair(a,b)#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define pb(x) push_back(x)using namespace std;typedef __int64 ll;const int NN = 30300;int n,m,k,qn;int a[NN];int cot[NN],ans[NN],block[NN],bnum,sum;struct query{    int l,r,idx;    bool isadd;    query(){}    query(int lx,int rx,int idxx,bool isaddx):l(lx),r(rx),idx(idxx),isadd(isaddx){}}q[NN*4];bool cmp(query x,query y){    if(block[x.l]==block[y.l])return x.r<y.r;    return x.l<y.l;}void init(){    qn=sum=0;    bnum=sqrt(n);    rep(i,1,n)cot[i]=0;    scanf("%d",&k);    rep(i,1,n)scanff(a[i]);    rep(i,1,n)block[i]=(i-1)/bnum+1;    scanf("%d",&m);    rep(i,1,m){    ans[i]=0;        int l1,r1,l2,r2;        scanff(l1);        scanff(r1);        scanff(l2);        scanff(r2);        q[++qn]=query(l1,r2,i,1);        q[++qn]=query(l1,l2-1,i,0);        q[++qn]=query(r1+1,r2,i,0);        if(r1+1<=l2-1)q[++qn]=query(r1+1,l2-1,i,1);    }    sort(q+1,q+1+qn,cmp);}void update(int val,bool isadd){    if(k-val<=0&&k-val<=n)return;    sum-=cot[val]*cot[k-val];    if(isadd)cot[val]++;    else cot[val]--;    sum+=cot[val]*cot[k-val];}void solve(){    int l=1,r=0;    rep(i,1,qn){        for(;r<q[i].r;r++)update(a[r+1],1);        for(;r>q[i].r;r--)update(a[r],0);        for(;l<q[i].l;l++)update(a[l],0);        for(;l>q[i].l;l--)update(a[l-1],1);        //printf("%d %d %d\n",l,r,sum);        if(q[i].isadd)ans[q[i].idx]+=sum;        else ans[q[i].idx]-=sum;    }    rep(i,1,m)printf("%d\n",ans[i]);}int main(){    while(scanf("%d",&n)!=EOF){        init();        solve();    }}


0 0