P9737 [COCI2022-2023#2] Lampice 题解
→更好的阅读体验
题目大意
题目链接:P9737 Lampice
给定一个坐标系(仅使用
要求在坐标轴上找到矩形(顶点坐标均为自然数),使每个点对的两个点均在矩形内或均在矩形外,最终输出满足条件的矩形个数。
题解
下面将讨论各个 subtask 中的可行解法(subtask 颜色表示个人认为的难度):
\text{\textcolor{#7de749}{Subtask 1 (28 pts)}}
特殊条件:
对于每种颜色的灯,
解法:
我们发现,如果我们将
①将
则
易得,该种情况下共有
②不将
先遍历矩形的下行
再遍历列
→时间复杂度最终为 (懒得写程序了()。
\text{\textcolor{#fe4f64}{Subtask 2 (12 pts)}}
特殊条件:
特殊条件:
特殊条件:
无特殊条件。
解法:
进一步优化 sub#3 的算法:
遍历矩形左端的列
此时问题就转化为了:找到 xor 和 = 0 且 长度至少为 2 的
tips:“长度至少为 2”这一条件可以后期处理(删去长度为 1 的情况数)。
→时间复杂度最终为
代码实现
//solution of P9737 [COCI2022-2023#2] Lampice
#include <bits/stdc++.h>
using namespace std;
#define MAXN 3010
#define int long long
mt19937 rng(random_device{}());
int m,n,k;
int a[MAXN][MAXN];
int solve(vector<int> v){
sort(v.begin(),v.end());
int cnt=1,ans=0;
for(int i=1;i<(int)v.size();++i){
if (v[i]!=v[i-1]) cnt=0;
ans+=cnt;
++cnt;
}
return ans;
}
signed main(){
//解绑快读
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
//生成均匀分布的随机数 (见sub#3题解)
uniform_int_distribution<int> dis(0,(1ll<<60)-1);
cin>>n>>m>>k;
++n,++m;//这里将所有坐标+1易于后期操作
for(int i=1;i<=k;i++){
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
++x1,++y1,++x2,++y2;//同理
int u=dis(rng);
a[x1][y1]^=u;//给点赋予随机值
a[x2][y2]^=u;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
a[i+1][j+1]^=a[i][j]^a[i+1][j]^a[i][j+1];//预处理
int ans=0;
for(int l=0;l<n;l++)
for(int r=l+2;r<=n;r++){//遍历矩形左右坐标
vector<int> v(m+1);
for(int i=0;i<=m;i++){
v[i]=a[l][i]^a[r][i];
}
ans+=solve(v);
for(int i=0;i<m;i++){//删去长度为1的子数组 (不要忘记了哦!!!)
ans-=(v[i]^v[i+1])==0;
}
}
cout<<ans<<endl;
return 0;
}