jzoj1495 宝石 解题报告[扫描线]

Description

见上帝动了恻隐之心,天后也想显示一下慈悲之怀,随即从口袋中取出一块魔术方巾,让身边的美神维纳斯拿到后堂的屏风上去试试,屏风是正方形的,高和宽方向上各划有m条鱼屏风的边平行的直线,平行直线间的距离为1厘米。这2m条直线共有m*m个交点,在某些交点上镶嵌着宝石。如果魔术方巾的边与屏风的边平行且魔术方巾触碰到屏风上镶嵌着的宝石,就将与这些宝石等值的金银送给人们。维纳斯想让魔术方巾触碰到的宝石的价值最多,可要在短短的1秒钟之内解决问题,也感到力不从心,你能帮帮她吗?

Input

输入文件gem.in的第一行有三个正整数m,n,k,数与数之间用一个空格分隔。其中m为屏风在高和宽方向上被划分出的直线数。魔术方巾为正方形的,它的边长为k厘米。N为屏风上宝石的个数。
接下来的n行,每行三个正整数,依次表示宝石所在直线的行号、列号、宝石的价值,数与数之间用一个空格分隔。

Output

输出文件gem.out只有一个正整数,为魔术方巾触碰到的宝石的最大价值总数。

Sample Input

10    4    4
1     1    9
2     3    5
6     2    12
4     5    6

Sample Output

23

Hint

【输入样例2】
10 4 3
1 1 9
2 3 5
6 2 12
4 5 6
【输出样例2】
18

【数据限制】
30%的数据,1≤m≤500,1≤n≤10000,1≤k≤100;
60%的数据,1≤m≤3000,1≤n≤10000,1≤k≤1000;
100%的数据,1≤m≤50000,1≤n≤50000,1≤k≤10000;

题目大意就是在一个正方形内给定一些点,用一个小正方形去覆盖,由于每个点的分数不同,因此肯定有所谓最大得分,算出最大得分就是我们的任务

我们放正方形,有一个点放在正方形的一角上是最优的,这里我们采用左下角

把输入的点按照x离散化,再按照y进行排序,考虑从下到上扫描线。线怎么来呢?我们把每个点置于小矩形的左下角,每个点就拥有了一个对应的范围,对于每一个范围我们把上边界所在直线进行扫描。

想象各点范围相交的地方肯定是这些点的分数都可以取到的。

在向上扫描的过程中,我们相当于是将一个长为m的矩形(离散化之后就是cnt),宽为k的矩形不断想上移动,然后去其中长为k的得分最大的一段。具体实现就是在扫描线的线段树上维护区间最大值就可以了。

下面附上代码:

#include<algorithm>
#include<cstdio>
using namespace std;

const int maxn=5e4+15;
int m,n,k,tot,cnt;
int left[maxn<<4],right[maxn<<4];
struct STAR
{
    int id,x,y,l;
    bool fl;
}a[maxn<<4],b[maxn<<4];
struct node
{
    int l,r,m,lazy;
}t[maxn<<4];
inline int read()
{
    char ch=getchar();
    int s=0,f=1;
    while (!(ch>=‘0‘&&ch<=‘9‘)) {if (ch==‘-‘) f=-1;ch=getchar();}
    while (ch>=‘0‘&&ch<=‘9‘) {s=(s<<3)+(s<<1)+ch-‘0‘;ch=getchar();}
    return s*f;
}
bool cmp(STAR a,STAR b) {return a.x<b.x;}
bool CMP(STAR a,STAR b) {if (a.y==b.y) return a.l>b.l;else return a.y<b.y;}
void build(int u,int l,int r)
{
    t[u].l=l;
    t[u].r=r;
    t[u].lazy=t[u].m=0;
    if (l==r) return;
    int mid=l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
}
void down(int u)
{
    if (t[u].lazy)
    {
        int k=t[u].lazy;
        t[u].lazy=0;
        t[u<<1].lazy+=k;
        t[u<<1|1].lazy+=k;
        t[u<<1].m+=k;
        t[u<<1|1].m+=k;
    }
}
void add(int u,int l,int r,int k)
{
    if (t[u].l>=l&&t[u].r<=r) {
        t[u].m+=k;
        t[u].lazy+=k;
        down(u);
        return;
    }
    down(u);
    int mid=t[u].l+t[u].r>>1;
    if (l<=mid) add(u<<1,l,r,k);
    if (r>mid) add(u<<1|1,l,r,k);
    t[u].m=max(t[u<<1].m,t[u<<1|1].m);
    return;
}
int query(int u,int l,int r)
{
    if (t[u].l>=l&&t[u].r<=r) return t[u].m;
    down(u);
    int ans=0,mid=t[u].l+t[u].r>>1;
    if (l<=mid) ans=query(u<<1,l,r);
    if (r>mid) ans=max(ans,query(u<<1|1,l,r));
    return ans;
}
int main()
{
    m=read();n=read();k=read();
    for (int i=1;i<=n;i++)//a数组用来离散化
    {
        a[i].x=read();a[i].y=read();a[i].l=read();
        a[i].id=i;
        a[i].fl=0;
        b[i].y=a[i].y;//扫描线左端点
        b[i].id=i;
        b[i].l=a[i].l;
    }
    tot=n;
    for (int i=1;i<=n;i++)
    {
        a[++tot].id=i;
        a[tot].x=a[i].x+k;
        a[tot].fl=1;
    }
    sort(a+1,a+1+tot,cmp);//按x排序
    for (int i=1;i<=tot;i++)
    {
        int tt=0;
        if (a[i].x==a[i-1].x&&i!=1) tt=cnt;
        else tt=++cnt;
        if (!a[i].fl) left[a[i].id]=tt;
        else right[a[i].id]=tt;
    }
    tot=n;
    for (int i=1;i<=n;i++)
    {
        b[++tot].id=b[i].id;//扫描线右端点
        b[tot].l=-b[i].l;
        b[tot].y=b[i].y+k;
    }
    sort(b+1,b+1+tot,CMP);//按y排序
    build(1,1,cnt);
    int ans=0;
    for (int i=1;i<=tot;i++)
    {
        if (b[i].l>0) {
            int sum=query(1,left[b[i].id],right[b[i].id]);//只有在b[i]的范围内才能加上b[i].l
            if (sum+b[i].l>ans) ans=b[i].l+sum;
        }
        add(1,left[b[i].id],right[b[i].id],b[i].l);
    }
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/xxzh/p/9278351.html

时间: 2024-10-14 04:27:57

jzoj1495 宝石 解题报告[扫描线]的相关文章

ACM-ICPC 2017 Asia HongKong 解题报告

ACM-ICPC 2017 Asia HongKong 解题报告 任意门:https://nanti.jisuanke.com/?kw=ACM-ICPC%202017%20Asia%20HongKong 按AC次序: D - Card collection In an online game, a player can collect different types of power cards. Each power card can enable a player to have a uni

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh童鞋的提醒. 勘误2:第7题在推断连通的时候条件写错了,后两个if条件中是应该是<=12 落了一个等于号.正确答案应为116. 1.煤球数目 有一堆煤球.堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形). -. 假设一共

[noip2011]铺地毯(carpet)解题报告

最近在写noip2011的题,备战noip,先给自己加个油! 下面是noip2011的试题和自己的解题报告,希望对大家有帮助,题目1如下 1.铺地毯(carpet.cpp/c/pas) [问题描述]为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有n 张地毯,编号从1 到n.现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上.地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的

ACdream 1203 - KIDx&#39;s Triangle(解题报告)

KIDx's Triangle Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description One day, KIDx solved a math problem for middle students in seconds! And than he created this problem. N

解题报告 之 CodeForces 91B Queue

解题报告 之 CodeForces 91B Queue Description There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue.

解题报告 之 POJ1226 Substrings

解题报告 之 POJ1226 Substrings Description You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings. Input The first li