zoukankan      html  css  js  c++  java
  • [BZOJ 3888] [Usaco2015 Jan] Stampede 【线段树】

    题目链接:BZOJ - 3888

    题目分析

    首先,计算出每个线段在 x 坐标 0 处出现的时间开始点和结束点,就转成了时间轴上的线段。

    然后就是看每条线段是否被 y 比它小的线段完全覆盖了。注意求出的时间点要离散化,然后应该使用时间轴上的区间来表示,两线段端点重合并不是有共同部分。

    将所有线段按照 y 从小到大排序之后,使用线段树判断它覆盖的区间是否已经都被前面的线段覆盖了。

    然后将它所覆盖的区间覆盖。

    就这样的一道题我WA了7次,还有救吗..

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <map>
    
    using namespace std;
    
    const int MaxN = 100000 + 5;
    
    map<int, int> M;
    
    int n, Top, Ans, MN;
    int NA[MaxN], T[MaxN * 4], D[MaxN * 4];
    
    inline int gmin(int a, int b) {return a < b ? a : b;}
    
    struct ES
    {
    	int s, t, Height;
    } E[MaxN];
    
    inline bool Cmp(ES e1, ES e2)
    {
    	return e1.Height < e2.Height;
    }
    
    inline void Paint(int x)
    {
    	T[x] = D[x] = 1;
    }
    
    inline void PushDown(int x)
    {
    	if (D[x] == 0) return;
    	Paint(x << 1);
    	Paint(x << 1 | 1);
    	D[x] = 0;
    }
    
    int Get(int x, int s, int t, int l, int r)
    {
    	if (l <= s && r >= t) return T[x];
    	PushDown(x);
    	int m = (s + t) >> 1, ret = 1;
    	if (l <= m) ret = gmin(ret, Get(x << 1, s, m, l, r));
    	if (r >= m + 1) ret = gmin(ret, Get(x << 1 | 1, m + 1, t, l, r));
    	return ret;
    }
    
    inline void Update(int x)
    {
    	T[x] = gmin(T[x << 1], T[x << 1 | 1]);
    }
    
    void Cover(int x, int s, int t, int l, int r)
    {
    	if (l <= s && r >= t) 
    	{
    		Paint(x);
    		return;
    	}
    	PushDown(x);
    	int m = (s + t) >> 1;
    	if (l <= m) Cover(x << 1, s, m, l, r);
    	if (r >= m + 1) Cover(x << 1 | 1, m + 1, t, l, r);
    	Update(x);
    }
    
    int main()
    {
    	scanf("%d", &n);
    	int x, y, r;
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d%d%d", &x, &y, &r);
    		E[i].Height = y;
    		E[i].s = (-x - 1) * r;
    		E[i].t = E[i].s + r;
    		NA[++Top] = E[i].s;
    		NA[++Top] = E[i].t;
    	}
    	sort(NA + 1, NA + Top + 1);
    	int p = 0;
    	for (int i = 1; i <= Top; ++i)	
    	{
    		if (i != 1 && NA[i] == NA[i - 1]) continue;
    		M[NA[i]] = ++p;
    	}
    	for (int i = 1; i <= n; ++i)
    	{
    		E[i].s = M[E[i].s];
    		E[i].t = M[E[i].t] - 1;
    	}
    	sort(E + 1, E + n + 1, Cmp);
    	MN = n * 2 + 5;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (Get(1, 1, MN, E[i].s, E[i].t) == 0) ++Ans;
    		Cover(1, 1, MN, E[i].s, E[i].t);
    	}
    	printf("%d
    ", Ans);
    	return 0;
    }
    

      

  • 相关阅读:
    迪杰斯特拉_优先队列 模板
    POJ3268(Dijkstra_邻接矩阵)
    Uva-10815
    Uva-10474
    同余方程
    欧几里得算法与扩展欧几里得算法
    大整数型的加法
    Uva442
    《哲学起步》读后感 读书笔记
    《论大战略》读后感 读书笔记
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4434000.html
Copyright © 2011-2022 走看看