zoukankan      html  css  js  c++  java
  • [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法

    题目链接:BZOJ - 1218

    题目分析

    可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形。

    坐标范围 <= 5000 ,直接 n^2 的二维前缀和,枚举每一个边长为 R - 1 的正方形就 AC 了 = =

    但是,尽管 O(n^2) 的算法能水过,lct1999 神犇仍然坚持要写 O(n logn) 算法虐掉这道题,于是我 Orz 他也学着写了一下。

    在神犇的讲解下,我写了这个算法:

    首先将 n 个点按照 x 坐标排序,用一条竖直的扫描线,从左到右扫描每个点。

    以这条扫描线为正方形的左边界,将在右边界之内的点都加入线段树,这个线段树是按照 y 坐标建立的。

    我们应该求出的是 y 坐标的一个和最大的长度为 R 的区间,加入一个点或删除一个点会影响它所在的 R 个区间,这些区间是连续的一段,所以加点和删点就是区间修改。

    又一次写区间修改不打标记,又一次被自己蠢哭了!

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    inline int gmax(int a, int b) {return a > b ? a : b;}
    inline int gmin(int a, int b) {return a < b ? a : b;}
    
    const int MaxN = 10000 + 5;
    
    int n, R, Ans, Head, Tail;
    int T[5000 * 4 + 15], D[5000 * 4 + 15];
    
    struct Point
    {
    	int x, y, w;
    	bool operator < (const Point &b) const
    	{
    		return x < b.x;
    	}
    } P[MaxN];
    
    inline void Update(int x)
    {
    	T[x] = gmax(T[x << 1], T[x << 1 | 1]);
    }
    
    inline void Paint(int x, int Num) 
    {
    	D[x] += Num;
    	T[x] += Num;
    }
    
    inline void PushDown(int x)
    {
    	if (D[x] == 0) return;
    	Paint(x << 1, D[x]);
    	Paint(x << 1 | 1, D[x]);
    	D[x] = 0;
    }
    
    inline void Add(int x, int s, int t, int l, int r, int Num)
    {
    	if (l <= s && r >= t) 
    	{
    		Paint(x, Num);
    		return;
    	}
    	PushDown(x);
    	int m = (s + t) >> 1;
    	if (l <= m) Add(x << 1, s, m, l, r, Num);
    	if (r >= m + 1) Add(x << 1 | 1, m + 1, t, l, r, Num);
    	Update(x);
    }
    
    int main()
    {
    	scanf("%d%d", &n, &R);
    	for (int i = 1; i <= n; ++i)
    		scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].w);
    	sort(P + 1, P + n + 1);
    	Head = 1; Tail = 0;
    	Ans = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		while (Head <= i && P[Head].x < P[i].x) 
    		{
    			Add(1, 0, 5000, P[Head].y, gmin(5000, P[Head].y + R - 1), -P[Head].w);	
    			++Head;
    		}
    		while (Tail < n && P[Tail + 1].x <= P[i].x + R - 1) 
    		{
    			++Tail;
    			Add(1, 0, 5000, P[Tail].y, gmin(5000, P[Tail].y + R - 1), P[Tail].w);
    		}
    		Ans = gmax(Ans, T[1]);
    	}
    	printf("%d
    ", Ans);
    	return 0;
    }
    

      

  • 相关阅读:
    dapper hepler帮助类
    别人在用你的什么技术在赚钱.其实你天天在做
    把asp.net mvc5 controller 单独放置在一个项目实例
    重写和动态创建 asp.net mvc 的控制器
    Linux 配置环境变量,环境变量优先级
    Redhat/ Centos/Ubuntu Linux sudo 权限配置,添加root权限
    Linux和window的文件传输 ( NFS篇 )
    安装R软件,R-3.5.3软件的下载、编译及安装
    yum 源
    瓜大无人船踩坑记3
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4364314.html
Copyright © 2011-2022 走看看