CF815D Karen and Cards 题解
题目描述
给定三维空间中的 \(n\) 个点 \((x_i,y_i,z_i)\) 。
求有多少个整点 \((x,y,z)\) 满足 \(1\le x\le p,1\le y\le q,1\le z\le r\) ,并且 \(\forall 1\le i\le n\) , \([x\gt x_i]+[y\gt y_i]+[z\gt z_i]\ge 2\) 。
数据范围
- \(1\le n,p,q,r\le 5\cdot 10^5,1\le x_i\le p,1\le y_i\le q,1\le z_i\le r\) 。
时间限制 \(\texttt{2s}\) ,空间限制 \(\texttt{512MB}\) 。
分析
固定 \(x\) ,统计怎样的 \((y,z)\) 会对答案产生贡献。
将所有点分为两类:
- \(x\le x_i\) :限制 \(y\gt y_i\and z\gt z_i\) 。
- \(x\gt x_i\) :限制 \(y\gt y_i\or z>z_i\) 。
第一类限制容易解决,将 \(y,z\) 的限制关于 \(x\) 做一个后缀 \(\max\) 即可,记为 \(ly_x,lz_x\) 。
记 \(mx_y\) 为满足 \(y_i\ge y\) 的所有第二类限制中的点, \(z_i\) 的最大值。
固定 \(y\) ,限制等价于 \(z\gt\max(mx_y,lz_{x})\) ,有 \(r-\max(mx_y,lz_x)\) 个点符合要求。
注意到第一类限制严格强于第二类限制,因此计算 \(mx\) 时,可以将第一类限制的点放进来,这样 \(mx\) 数组对所有的\(x\)都一样,可以预处理。
目标转化为求 \(\sum_{x=1}^p\sum_{y=ly_x+1}^q\big(r-max(mx_y,lz_x)\big)\) 。
从小到大枚举 \(x\) ,那么 \(ly_x,lz_x\) 逐渐变小,维护内层求和的答案。
由于 \(mx_y\) 随着 \(y\) 增大而减小,相当于右上角有一个阶梯状网格图,维护网格图与右上角矩形(初始为空)的交集大小。
用两个指针记录右上边界,增量可以 \(\mathcal O(1)\) 维护。
时间复杂度 \(\mathcal O(n+p+q+r)\) 。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int n,p,q,r;
long long cur,res;
int ly[maxn],lz[maxn],mx[maxn],nx[maxn];
inline int read()
{
int q=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) q=10*q+ch-'0',ch=getchar();
return q;
}
inline void chmax(int &x,int y)
{
if(x<=y) x=y;
}
int main()
{
scanf("%d%d%d%d",&n,&p,&q,&r);
for(int i=1;i<=n;i++)
{
int x=read(),y=read(),z=read();
chmax(ly[x],y),chmax(lz[x],z),chmax(mx[y],z);
}
for(int x=p;x>=1;x--) chmax(ly[x],ly[x+1]),chmax(lz[x],lz[x+1]);
for(int y=q;y>=1;y--) chmax(mx[y],mx[y+1]);
for(int y=q;y>=1;y--) for(int i=mx[y];i>mx[y+1];i--) nx[i]=y;
for(int x=1,y=q,z=r;x<=p;x++)
{
while(y>ly[x]) cur+=r-max(mx[y--],z);
while(z>lz[x]) cur+=q-max(nx[z--],y);
res+=cur;
}
printf("%lld\n",res);
return 0;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/17477741.html
浙公网安备 33010602011771号