zoukankan      html  css  js  c++  java
  • 【题解】洛谷P1502 窗口的星星

    Des

    晚上,小卡从阳台望出去,“哇~~~~好多星星啊”,但他还没给其他房间设一个窗户。

    天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。

    这时小卡使用了超能力(透视术)知道了墙后面每个星星的位置和亮度,但是小卡发动超能力后就很疲劳,只好拜托你告诉他最多能够有总和多亮的星星能出现在窗口上。

    ( exttt{Data Range:})

    (1le T le 10)

    (1le n le 10^4)

    (1le W,H le 10^6)

    (0le x_i,y_i < 2^{31})

    Sol

    考虑把「星星在窗子所在的矩形中」转化为「窗子的右上角在星星上面 H,右边 W 的矩形中」。这样就可以把整个问题转化为找一个点使得覆盖该点的矩形最多。

    image

    (如图,矩形框住了两个星星)

    现在考虑窗户边框的限制。

    image

    如图,虽然窗户的右上角不能落在黑框,只能落在黑框里,但将黑框的长和宽的两端都减小一个 eps(极小值)得到红框后,窗户的右上角就可以落在红框里的任何一个地方了。

    但是如果减小 eps,星星所对应的矩形的坐标就变成了实数。

    这时出现了一种方法,将矩形的长宽在两端都减小 0.5,然后把坐标轴向上平移、向右平移 0.5 个单位。最后生成的矩形左下角是 ((x,y)),右上角是 (x+W-1,y+H-1)

    这样做为什么是正确的呢?长宽减小的数值需要保证原本有交的矩形仍然有交。由于星星的坐标是整数,所以极限情况(可能会在矩形缩小后没有交的情况)如下图:

    image

    在减小 0.5 之后仍然有交(只不过在对 line 进行排序的时候需要把 l 为正的排在前面)。而两端减小 0.5,合起来就是 1,这导致生成的矩形在平移坐标轴之后的坐标可以是整数。

    所以这其实是一个很巧妙的方法,很多题解没说清楚。

    My code

    和模板不一样,这道题线段树上的点映射到的就是平面上的点。

    const int N = 2e4 + 10;
    int T, n, W, H, stc, ans, v[N];
    struct node {
    	int x, ya, yb, k;
    	bool operator<(const node &b) { return x < b.x || (x == b.x && k > b.k); }
    } a[N];
    
    struct segmentTree {
    	#define lc(x) (x << 1)
    	#define rc(x) (x << 1 | 1)
    	int mx[N << 2], tag[N << 2];
    	void pdown(int p) {
    		if(tag[p]) {			
    			mx[lc(p)] += tag[p], mx[rc(p)] += tag[p];
    			tag[lc(p)] += tag[p], tag[rc(p)] += tag[p];
    			tag[p] = 0;
    		}
    	}
    	void modify(int l, int r, int p, int x, int y, int k) {
    		if(l >= x && r <= y) {
    			mx[p] += k, tag[p] += k;
    			return;
    		}
    		pdown(p);
    		int mid = (l + r) >> 1;
    		if(x <= mid) modify(l, mid, lc(p), x, y, k);
    		if(y > mid) modify(mid + 1, r, rc(p), x, y, k);
    		mx[p] = max(mx[lc(p)], mx[rc(p)]);
    	}
    	#undef lc
    	#undef rc
    } st;
    
    inline int find(int x) {
    	return lower_bound(v + 1, v + stc + 1, x) - v;
    }
    
    void clear() {
    	stc = 0, ans = 0;
    	memset(st.mx, 0, sizeof st.mx);
    	memset(st.tag, 0, sizeof st.tag);
    }
    
    int main() {
    	ios::sync_with_stdio(false); cin.tie(nullptr);
    	for(cin >> T; T; T--) {
    		cin >> n >> W >> H;
    		clear();
    		for(int i = 1, x, y, l; i <= n; i++) {
    			cin >> x >> y >> l;
    			a[2 * i - 1] = node{x, y, y + H - 1, l};
    			a[2 * i] = node{x + W - 1, y, y + H - 1, -l};
    			v[++stc] = y, v[++stc] = y + H - 1;
    		}
    		sort(a + 1, a + 2 * n + 1);
    		sort(v + 1, v + stc + 1);
    		stc = unique(v + 1, v + stc + 1) - v - 1;
    		for(int i = 1; i <= n * 2; i++) {
    			ans = max(ans, st.mx[1]);
    			st.modify(1, stc, 1, find(a[i].ya), find(a[i].yb), a[i].k);
    		}
    		cout << ans << '
    ';
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    UML类图学习总结
    Java和C# RSA加解密相互通信和使用公钥加密传输
    C#des加密算法指定键的大小对于此算法无效
    WCF--找不到具有绑定 BasicHttpBinding 的终结点的与方案 https 匹配的基址。注册的基址方案是 [http]。
    IIS7 使用server farms 进行负载均衡
    iis7 未注册framework4 导致 莫名的404错误
    启用代理导致 有道云笔记未知错误、网络错误和OneDrive断线
    AspNetCore发布到Centos7
    c# 操作临时数据---XML操作
    c# 获取程序目录
  • 原文地址:https://www.cnblogs.com/huaruoji/p/p1502.html
Copyright © 2011-2022 走看看