zoukankan      html  css  js  c++  java
  • HDU5213 Lucky 莫队算法 容斥定理

      题意:有一串数字 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;
    }
    View Code
  • 相关阅读:
    大组合取模之:1<=n<=m<=1e6,1<=p<=1e9
    大组合数取模之lucas定理模板,1<=n<=m<=1e9,1<p<=1e6,p必须为素数
    fzu2020( c(n,m)%p,其中n, m, p (1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数) )
    lucas定理证明
    各类小公式
    x^a=b(mod c)求解x在[0,c-1]上解的个数模板+原根求法
    快速幂+乘模 模板
    hdu1695(容斥 or 莫比乌斯反演)
    poj1845(二分快速求等比数列模M和)
    2018JAVA面试题附答案
  • 原文地址:https://www.cnblogs.com/bxd123/p/10919825.html
Copyright © 2011-2022 走看看