zoukankan      html  css  js  c++  java
  • HDU5213 Lucky(莫队+容斥)

    这道题能看的出可以离线查询,不难想到莫队,但是寻常莫队每个询问只有一段,这样只需要排序即可

    这里有两段,如果只按一段排序,那么复杂度显然得不到保证,以后不知道后面一段怎么样。

    因此这里提出了一个想法就是,如果有多段,那么可以通过容斥原理来解决这个问题,把他变成多个询问的加减,这样复杂度就ok了

    我们想要查询的是取两个数使他的和为k,从纸上画画就知道应该如何容斥。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int  N=1e5+10;
    struct node{
        int x1,x2;
        int y1,y2;
        ll ans;
    }q[N<<1];
    struct Node{
        int l,r;
        ll ans;
        int fa;
        int flag;
    }s[N<<1];
    int a[N],k;
    int pos[N];
    ll cnt[N];
    ll res;
    bool cmp(Node a,Node b){
        if(pos[a.l]==pos[b.l])
            return a.r<b.r;
        return pos[a.l]<pos[b.l];
    }
    void add(int x){
        if(k-a[x]>0)
        res+=cnt[k-a[x]];
        cnt[a[x]]++;
    }
    void sub(int x){
        cnt[a[x]]--;
        if(k-a[x]>0)
        res-=cnt[k-a[x]];
    }
    int main(){
        int n;
        int i;
        while(cin>>n){
            cin>>k;
            res=0;
            for(i=1;i<=n;i++)
                cnt[i]=0;
            int block=sqrt(n);
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
                pos[i]=(i-1)/block+1;
            }
            int m;
            cin>>m;
            int cnt=0;
            for(i=1;i<=m;i++){
                scanf("%d%d%d%d",&q[i].x1,&q[i].y1,&q[i].x2,&q[i].y2);
                q[i].ans=0;
                cnt++;
                s[cnt].l=q[i].x1,s[cnt].r=q[i].y2,s[cnt].ans=0,s[cnt].fa=i,s[cnt].flag=1;
                cnt++;
                s[cnt].l=q[i].y1+1,s[cnt].r=q[i].x2-1,s[cnt].ans=0,s[cnt].fa=i,s[cnt].flag=1;
                cnt++;
                s[cnt].l=q[i].x1,s[cnt].r=q[i].x2-1,s[cnt].ans=0,s[cnt].fa=i,s[cnt].flag=0;
                cnt++;
                s[cnt].l=q[i].y1+1,s[cnt].r=q[i].y2,s[cnt].ans=0,s[cnt].fa=i,s[cnt].flag=0;
            }
            sort(s+1,s+1+cnt,cmp);
            int l=1;
            int r=0;
            for(i=1;i<=cnt;i++){
                while(s[i].l<l)
                    add(--l);
                while(s[i].l>l)
                    sub(l++);
                while(s[i].r>r)
                    add(++r);
                while(s[i].r<r)
                    sub(r--);
                s[i].ans=res;
                int x=s[i].fa;
                int flag=s[i].flag;
                if(flag){
                    q[x].ans+=s[i].ans;
                }
                else{
                    q[x].ans-=s[i].ans;
                }
            }
            for(i=1;i<=m;i++)
                printf("%lld
    ",q[i].ans);
        }
    }
    View Code
  • 相关阅读:
    20199108 2019-2020-2 《网络攻防实践》第8周作业
    20199108 2019-2020-2 《网络攻防实践》第7周作业
    攻防作业报告提交
    Spring整合HBase
    基于注解的Spring AOP示例
    Spring AOP基本概念
    在RichFaces中使用Facelets模板
    算法导论读书笔记(19)
    算法导论读书笔记(18)
    算法导论读书笔记(17)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12586080.html
Copyright © 2011-2022 走看看