zoukankan      html  css  js  c++  java
  • 牛客网暑期ACM多校训练营(第五场)I(树状数组)

    题目描述:

        有 n 个点,一个点集 S 是好的,当且仅当对于他的每个子集 T,存在一个右边无限长的矩形,使得这个矩形包含了 T,但是和 S-T 没有交
        求这 n 个点里有几个好的点集
    1<=n<=10^5

    题目分析:

        首先要小小吐槽一下这个题目的题面。三个人三双眼睛看这个题都是愣是一直都看不明白题意。

        而当我们明白题目在说些什么之后,其实这个题目就可以去做了。

        我们要求总的方案数,那么我们可以分为多种情况进行描述

        1):当只选取1个点时,我们可以发现,任何一个点都满足题意。

        2):当我们选取2个点时,我们可以发现如果要满足一个无限向右的矩形只框住一个点,当且仅当两个点的纵坐标不相同。因此,对于选2个点的总的方案数等于C(n,2)-C(纵坐标相同的个数,2)

        3):当我们选3个点的时候(假设三个点为a,b,c),我们可以发现,当我们选取{a,b}作为子集,倘如第三个点c在{a,b}的右边,则我们发现由{a,b}组成的矩形一定包含{c},故不成立。因此{c}必定在{a,b}的左边,即当且仅当三个点的能够构成一个'<'号的形式才能够符合题意。

        4):当选4个点及以上时,我们发现不管怎么样摆,均不可能出现3)的情况,故4个点以上的点是不合理的。

        因此现在我们只需要处理的就是3)中的情况。对于3)的情况。我们只要求出在第i个点之前,有多少个点的x坐标比当前点大(记位below),再求出在第i个点之后有多少个点的x坐标比当前点大(记位above),那么对于第i个点而言,该点的方案数即为below*above了。

        而对于below和above值的维护,我们需要先将y坐标进行离散化,然后将数组按照x坐标进行排序,然后用树状数组对区间进行维护即可。

    代码:

    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    struct node{
        int x,y;
        bool operator<(const node &b)const{
            return x>b.x;
        }
    }q[maxn];
    int hav[maxn],san[maxn],bit[maxn];
    int lowbit(int x){
        return x&-x;
    }
    void update(int x,int num){
        while(x<maxn){
            bit[x]+=num;
            x+=lowbit(x);
        }
    }
    int query(int x){
        int res=0;
        while(x){
            res=(res+bit[x])%mod;
            x-=lowbit(x);
        }
        return res;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&q[i].x,&q[i].y);
            san[i]=q[i].y;
        }
        //sort(q+1,q+1+n);
        sort(san+1,san+1+n);//离散化
        int tot=unique(san+1,san+1+n)-san-1;
        for(int i=1;i<=n;i++){
            q[i].y=lower_bound(san+1,san+1+tot,q[i].y)-san;
            hav[q[i].y]++;
        }
        ll ans=0;
        ans=(0ll+n+1ll*n*(n-1)/2)%mod;//求出第一种和第二种的情况的方案数
        for(int i=1;i<=tot;i++){//减去纵坐标相同的情况
            ans=(ans-1ll*hav[i]*(hav[i]-1)/2+mod)%mod;
        }
        int pre=1;
        sort(q+1,q+1+n);
        for(int i=1;i<=n;i++){
            int above=query(q[i].y-1);
            int below=query(tot)-query(q[i].y);
            ans=(ans+1ll*above*below%mod)%mod;
            if(q[i].x!=q[i+1].x){
                while(pre<=i){//树状数组更新
                    update(q[pre].y,1),pre++;
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    Python+Apache环境搭建
    离线Python环境搭建
    Docker+Nginx+Vue部署
    Docker部署Flask
    Web服务器根据url参数代理
    javaweb各种框架组合案例(五):springboot+mybatis+generator
    javaweb各种框架组合案例(四):maven+spring+springMVC+spring data jpa(hibernate)【失败案例】
    在无界面centos7上部署MYSQL5.7数据库
    关于通过ip或者域名直接访问工程的问题
    在无界面centos7上部署jdk和tomcat
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007248.html
Copyright © 2011-2022 走看看