二维坐标系里有n个点,第i个点的坐标是(x[i],y[i])。
所有的x[i]互异,所有的y[i]互异。
设P是这n个点的某个子集,maxX是该子集的x的最大值,minX是该子集的x的最小值,
maxY是该子集的y的最大值,minY是该子集的y的最小值。
显然(maxX, minX, maxY, minY)确定了一个矩形,我们不妨假设该矩形内部(含边界)共有k个点,
我们定义点集P的价值f(P) = k。
对于所有不同的点集p,输出f(p)累加的和,答案模998244353。
输入格式
第一行,一个整数n。 1<=n<=200000。
接下来有n行,第i行是x[i]和y[i], -1e9<=x[i],y[i]<=1e9。
输出格式
一个整数。
输入/输出例子1
输入:
3
-1 3
2 1
3 -2
输出:
13
输入/输出例子2
输入:
4
1 4
2 1
3 3
4 2
输出:
34
输入/输出例子3
输入:
10
19 -11
-3 -12
5 3
3 -15
8 -14
-9 -20
10 -9
0 2
-7 17
6 -6
输出:
7222
站外题,写了四颗树状数组但是样例 3 过不了,不知道哪里出了问题。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define lowbit(x) x&(-x)
#define N 200005
const int mod=998244353;
//2^-1=2^(mod-2)
int n,m,i,j,ans,k,x;
int t1[N<<1],t2[N<<1],t3[N<<1],t4[N<<1],qpow[N<<1];
int cnt1[N],cnt2[N],cnt3[N],cnt4[N],num[N<<1];
struct ren{
int a,b,id;
}d[N];
bool cmp1(ren x,ren y){
if(x.a!=y.a) return x.a<y.a;
return x.b>y.b;
}//左上
bool cmp2(ren x,ren y){
if(x.a!=y.a) return x.a>y.a;
return x.b>y.b;
}//右上
bool cmp3(ren x,ren y){
if(x.a!=y.a) return x.a<y.a;
return x.b<y.b;
}//左下
bool cmp4(ren x,ren y){
if(x.a!=y.a) return x.a>y.a;
return x.b<y.b;
}//右下
int q1(int x){
int sum=0;
for(;x>=1;x-=lowbit(x)) sum+=t1[x];
return sum;
}
int u1(int x,int k){
for(;x<=(n*2);x+=lowbit(x)) t1[x]+=k;
}
int q2(int x){
int sum=0;
for(;x>=1;x-=lowbit(x)) sum+=t2[x];
return sum;
}
int u2(int x,int k){
for(;x<=(n*2);x+=lowbit(x)) t2[x]+=k;
}
int q3(int x){
int sum=0;
for(;x>=1;x-=lowbit(x)) sum+=t3[x];
return sum;
}
int u3(int x,int k){
for(;x<=(n*2);x+=lowbit(x)) t3[x]+=k;
}
int q4(int x){
int sum=0;
for(;x>=1;x-=lowbit(x)) sum+=t4[x];
return sum;
}
int u4(int x,int k){
for(;x<=(n*2);x+=lowbit(x)) t4[x]+=k;
}
signed main(){
scanf("%lld",&n);
qpow[0]=1;for(i=1;i<=n*2;i++) qpow[i]=qpow[i-1]*2%mod;
for(i=1;i<=n;i++){
scanf("%lld%lld",&d[i].a,&d[i].b);
num[++k]=d[i].a,num[++k]=d[i].b;
d[i].id=i;
}
sort(num+1,num+k+1);
k=unique(num+1,num+k+1)-num-1;
for(i=1;i<=n;i++){
d[i].a=lower_bound(num+1,num+k+1,d[i].a)-num;
d[i].b=lower_bound(num+1,num+k+1,d[i].b)-num;
}
sort(d+1,d+1+n,cmp1);
for(i=1;i<=n;i++){
cnt1[d[i].id]=q1(n<<1)-q1(d[i].b-1);
u1(d[i].b,1);
}
sort(d+1,d+1+n,cmp2);
for(i=1;i<=n;i++){
cnt2[d[i].id]=q2(n<<1)-q2(d[i].b-1);
u2(d[i].b,1);
}
sort(d+1,d+1+n,cmp3);
for(i=1;i<=n;i++){
cnt3[d[i].id]=q3(d[i].b);
u3(d[i].b,1);
}
sort(d+1,d+1+n,cmp4);
for(i=1;i<=n;i++){
cnt4[d[i].id]=q4(d[i].b);
u4(d[i].b,1);
}
for(i=1;i<=n;i++){
ans=(ans+qpow[cnt1[i]-1]%mod*qpow[cnt4[i]-1]%mod*qpow[cnt2[i]]%mod*qpow[cnt3[i]]%mod)%mod;
ans=(ans+qpow[cnt2[i]-1]%mod*qpow[cnt3[i]-1]%mod*qpow[cnt1[i]]%mod*qpow[cnt4[i]]%mod)%mod;
ans=(ans-qpow[cnt1[i]-1]%mod*qpow[cnt4[i]-1]%mod*qpow[cnt2[i]-1]%mod*qpow[cnt3[i]-1]%mod)%mod;
ans=(ans+qpow[n-1])%mod;
}
printf("%lld\n",ans);
return 0;
}
/*
以每个点构建直角坐标系
则有四个象限
包含原点条件有:
1.一、三象限必选一个,二、四象限随意;
2.二、四象限必选一个,一、三象限随意;
显然以上两种情况是有重复计算贡献的,也就是重复计算了四个象限都选的情况
所以是简单容斥
记四个象限点数分别为s1、s2、s3、s4
则对答案的贡献为:
2^(s1-1)*2^(s3-1)*2^s2*2^s4+2^(s2-1)*2^(s4-1)*2^s1*2^s3-2^(s1-1)*2^(s2-1)*2^(s3-1)*2^(s4-1)
位于四个方位点的数量是二维偏序,用树状数组维护。
对了,还要离散化
*/