概述
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6681
题意:现在有个矩形的蛋糕,并在蛋糕上建立笛卡尔坐标系,原点在左下角,一个人在蛋糕上切了 k k k刀,每一刀可以看成一条射线,射线起点在 ( x , y ) (x,y) (x,y)向四个方向射出,问所有射线最后将蛋糕切成了多少个部分。数据保证没有射线沿着边界并且没有两条射线在同一条直线上。
解题心得:由于数据已经排除了很多难得处理的数据,这个题就仅仅是离散化后一个树状数组维护就行了。将所有的射线按方向不同分别存放,然后都按照起点 y y y值大小排序,处理向上的射线时,从大到小枚举,如果射向左右的射线起点 y y y坐标大于枚举的向上射线起点 y y y坐标,就按照起点 x x x坐标放在树状数组中,处理向下的射线则按起点 y y y坐标从小到大枚举,方法是相同的。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+100;
struct Line {//存储射线,0123分别表示上下左右
int x, y, dir;
}line[maxn];
struct Line2 {//仅仅存储每条射线的起点坐标
int x, y;
bool operator < (const Line2& x) const {
return y > x.y;
}
};
vector <int> ve;//用于离散化
vector <Line2> Down, Up, Left, Right;//按方向存储不同射线
int n, m, k, sum[maxn];
long long ans;
void init() {
Down.clear();
Up.clear();
Left.clear();
Right.clear();
ve.clear();
ans = 1;
memset(sum, 0, sizeof sum);
scanf("%d%d%d",&n, &m, &k);
for(int i=1;i<=k;i++) {
char s[5];
scanf("%d%d%s", &line[i].x, &line[i].y, s);
ve.push_back(line[i].x);
ve.push_back(line[i].y);
//0123分别表示上下左右
if(s[0] == 'U') line[i].dir = 0;
if(s[0] == 'D') line[i].dir = 1;
if(s[0] == 'L') line[i].dir = 2;
if(s[0] == 'R') line[i].dir = 3;
}
sort(ve.begin(), ve.end());
ve.erase(unique(ve.begin(), ve.end()), ve.end());
for(int i=1;i<=k;i++) {
line[i].x = lower_bound(ve.begin(), ve.end(), line[i].x) - ve.begin() + 1;
line[i].y = lower_bound(ve.begin(), ve.end(), line[i].y) - ve.begin() + 1;
if(line[i].dir == 0) Up.push_back({line[i].x, line[i].y});
if(line[i].dir == 1) Down.push_back({line[i].x, line[i].y});
if(line[i].dir == 2) Left.push_back({line[i].x, line[i].y});
if(line[i].dir == 3) Right.push_back({line[i].x, line[i].y});
}
sort(Up.begin(), Up.end());
sort(Down.begin(), Down.end());
sort(Left.begin(), Left.end());
sort(Right.begin(), Right.end());
}
int lowbit(int x) {
return x&-x;
}
void add(int pos, int va) {
while(pos < maxn) {
sum[pos] += va;
pos += lowbit(pos);
}
}
int getSum(int pos) {
int Sum = 0;
while(pos) {
Sum += sum[pos];
pos -= lowbit(pos);
}
return Sum;
}
void checke_up() {//枚举向上的射线
int IndexL = 0, IndexR = 0;
for(int i=0;i<Up.size();i++) {
int Y = Up[i].y;
while(IndexL < Left.size() && Left[IndexL].y >= Y) {
add(1, 1);
add(Left[IndexL].x+1, -1);
IndexL++;
}
while(IndexR < Right.size() && Right[IndexR].y >= Y) {
add(Right[IndexR].x, 1);
IndexR++;
}
ans += getSum(Up[i].x);
}
}
void checke_down() {//枚举向下的射线
memset(sum, 0, sizeof sum);
int IndexL = Left.size()-1, IndexR = Right.size()-1;
for(int i=Down.size()-1;i>=0;i--) {
int Y = Down[i].y;
while(IndexL >= 0 && Left[IndexL].y <= Y) {
add(1, 1);
add(Left[IndexL].x+1, -1);
IndexL--;
}
while(IndexR >= 0 && Right[IndexR].y <= Y) {
add(Right[IndexR].x, 1);
IndexR--;
}
ans += getSum(Down[i].x);
}
}
int main() {
// freopen("1.in.txt", "r", stdin);
int t; scanf("%d", &t);
while(t--) {
init();
checke_up();
checke_down();
printf("%lldn", ans);
}
return 0;
}
最后
以上就是粗犷白昼为你收集整理的HDU:6681-Rikka with Cake的全部内容,希望文章能够帮你解决HDU:6681-Rikka with Cake所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复