码迷,mamicode.com
首页 > 其他好文 > 详细

【atcoder】Enclosed Points [abc136F]

时间:2019-08-04 22:35:59      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:转化   put   display   image   cstring   enc   sort   inline   解决问题   

  题目传送门:https://atcoder.jp/contests/abc136/tasks/abc136_f

  题目大意:在平面上有$n$个点我们,定义一个点集的权值为平面上包含这个点集的最小矩形所包含的点个数(矩形的边与坐标轴平行),求所有非空点集的权值和,保证每个点的横纵坐标互不相同。

  先考虑转化一下,求每个点被多少个点集$S$的矩形包含,假设我们当前考虑的是点$i$,那么可以分成两种情况:$i \in S$或$i \notin S$。

    1. 对于$i \in S$的情况,容易发现点$i$对所有包含$i$的点集有贡献,这里的贡献为$2^(n-1)$。

    2. 对于$i \notin S$的情况,因为每个点的横纵坐标互不相同,所以点$i$把整个坐标系划分成了4个区域

技术图片

    那么若点集$S$的矩形包含点$i$,那么必存在$p,q \in S,p \in A,q \in D$或$p \in B,q \in D$。

    设$A$区域中的点数量为$a$,$B$区域中的点数量为$b$,$C$区域中的点数量为$c$,$D$区域中的点数量为$d$,容斥可知这里的贡献为$(2^a-1)2^b2^c(2^d-1)+2^a(2^b-1)(2^c-1)2^d-(2^a-1)(2^b-1)(2^c-1)(2^d-1)$。

  计算每个区域的点数可以将点排序离散化后用树状数组维护,于是就可以在$O(n \log n)$的时间复杂度下解决问题。

  代码:

技术图片
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define mod 998244353
#define maxn 200010
inline ll read()
{
    ll x=0; char c=getchar(),f=1;
    for(;c<0||9<c;c=getchar())if(c==-)f=-1;
    for(;0<=c&&c<=9;c=getchar())x=x*10+c-0;
    return x*f;
}
inline void write(ll x)
{
    static char buf[20],len; len=0;
    if(x<0)x=-x,putchar(-);
    for(;x;x/=10)buf[len++]=x%10+0;
    if(!len)putchar(0);
    else while(len)putchar(buf[--len]);
}
inline void writesp(ll x){write(x); putchar( );}
inline void writeln(ll x){write(x); putchar(\n);}
struct Data{
    int x,id;
}num[maxn];
struct point{
    int x,y,rk;
}a[maxn];
int n;
bool cmp1(Data a,Data b){return a.x<b.x;}
bool cmp2(point a,point b){return a.x<b.x;}
inline ll power(ll a,ll b)
{
    ll ans=1;
    for(;b;b>>=1,a=a*a%mod)
        if(b&1)ans=ans*a%mod;
    return ans;
}
int bit1[maxn],bit2[maxn];
void add1(int x,int k){for(;x<=n;x+=x&(-x))bit1[x]+=k;}
int getsum1(int x){int sum=0; for(;x;x-=x&(-x))sum+=bit1[x]; return sum;}
void add2(int x,int k){for(;x<=n;x+=x&(-x))bit2[x]+=k;}
int getsum2(int x){int sum=0; for(;x;x-=x&(-x))sum+=bit2[x]; return sum;}
int main()
{
    n=read();
    for(int i=1;i<=n;i++){
        a[i].x=read(); a[i].y=read();
        num[i].x=a[i].y; num[i].id=i;
    }
    std::sort(num+1,num+n+1,cmp1);
    for(int i=1;i<=n;i++)
        a[num[i].id].rk=i;
    std::sort(a+1,a+n+1,cmp2);
    for(int i=1;i<=n;i++)
        bit1[i]=0,bit2[i]=i&(-i);
    ll ans=0;
    for(int i=1;i<=n;i++){
        add2(a[i].rk,-1);
        int A=getsum1(a[i].rk),B=getsum1(n)-getsum1(a[i].rk),C=getsum2(a[i].rk),D=getsum2(n)-getsum2(a[i].rk);
        ll totA=power(2,A),totB=power(2,B),totC=power(2,C),totD=power(2,D);
        ans=(ans+(totA-1)*totB%mod*totC%mod*(totD-1))%mod;
        ans=(ans+totA*(totB-1)%mod*(totC-1)%mod*totD)%mod;
        ans=(ans-(totA-1)*(totB-1)%mod*(totC-1)%mod*(totD-1)%mod+mod)%mod;
        ans=(ans+power(2,n-1))%mod;
        add1(a[i].rk,1);
    }
    writeln(ans);
    return 0;
}
abc136F

 

【atcoder】Enclosed Points [abc136F]

标签:转化   put   display   image   cstring   enc   sort   inline   解决问题   

原文地址:https://www.cnblogs.com/quzhizhou/p/11300139.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!