我是靠谱客的博主 粗犷白昼,最近开发中收集的这篇文章主要介绍HDU:6681-Rikka with Cake,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接: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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部