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
  • 相关阅读:
    真正的e时代
    在线手册
    UVA 10616 Divisible Group Sums
    UVA 10721 Bar Codes
    UVA 10205 Stack 'em Up
    UVA 10247 Complete Tree Labeling
    UVA 10081 Tight Words
    UVA 11125 Arrange Some Marbles
    UVA 10128 Queue
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/bxd123/p/10919825.html
Copyright © 2011-2022 走看看