碎碎念
第一点:本题有一定思维难度,先奉上纯暴力解法。明天开始要准备期末考试了,最近刷题的时间会比较少。
7月份,我会卷土重来,完成前缀和、树状数组。
第二点:对于一题多解的理解我肤浅了,老码农建议我,每一道题要做透,
不是为了AC而AC,能把自己所学知识融会贯通,提升思维能力才是关键所在。
第三点:平时养成注意细节习惯。
例如:代码19行,最初我随手写成
代码语言:javascript复制 scanf("%lld", &n);
正确的应该是(虽然不影响执行结果)
代码语言:javascript复制 scanf("%d", &n);
题目:P7149 [USACO20DEC] Rectangular Pasture S
题目原文请移步下面的链接
- https://www.luogu.com.cn/problem/P7149
- 参考题解:https://www.luogu.com.cn/problem/solution/P7149
- 标签:
OI
、USACO
、前缀和
、树状树组
- 难度:
普及 /提高
题解
思路
- 题解大家可移步看这里,很多童鞋写了各种解法
- https://www.luogu.com.cn/problem/solution/P7149
- 枚举上下边界(即i,j)由于每行每列都不相同,所以我们很愉快的不用考虑同一行或同一列有重复情况, 这个时候再枚举左右边界,用左边可放置的栅栏数*右边可放置的栅栏数
- 代码中加入注释,便于理解
代码
代码语言:javascript复制#include <bits/stdc .h>
using namespace std;
#define endl 'n';
struct edge {
int x, y;
};
bool cmp(edge a, edge b) {
if (a.x == b.x) {
return a.y < b.y;
}
return a.x < b.x;
}
void best_coder() {
int n;
scanf("%d", &n);
vector<edge> a(n);
for (int i = 0; i < n; i) {
scanf("%d%d", &a[i].x, &a[i].y);
}
sort(a.begin(), a.end(), cmp);
long long ans = 1;
vector<long long> lj(n); // 当a[j].y < a[j].i,即当j处于左边时,有多少个可以包裹住j的位置
vector<long long> rj(n); // 与lj同理
for (int i = 0; i < n; i) {
long long li = 0; // 有多少个位置可以从左侧包裹住i的位置
long long ri = 0; // 同理
ans;
for (int j = i - 1; j >= 0; --j) {
if (a[i].y > a[j].y) {
ans = (lj[j] 1) * (ri 1);
rj[j]; // j在i左侧时,对于j来说,i是一个可以从右侧包裹住j的位置
li; // 当j在i左边时,j所处的位置一定能包裹住i
} else {
ans = (li 1) * (rj[j] 1);
lj[j]; // 这两个与上文一个原理
ri;
}
}
}
printf("%lld", ans);
}
void happy_coder() {
}
int main() {
// 提升cin、cout效率
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
// 小码匠
best_coder();
// 最优解
// happy_coder();
// 返回
return 0;
}