• B. Beam Cannon【2014上海邀请赛】


    B. Beam Cannon

    题意

    (n) 个点和一个长 (W)(H) 的矩形,问平移这个矩形最多能覆盖多少个点

    思路

    对于每一个点,考虑什么样的矩形能覆盖它,考虑矩形的中心点就可以,这样一个点对应一个矩形,然后就是求 (n) 个矩形覆盖次数最多的区域

    用线段树区间查最大就可以

    #include<bits/stdc++.h>
    #define mid (l+r>>1)
    #define lo (o<<1)
    #define ro (o<<1|1)
    using namespace std;
    
    typedef long long ll;
    
    const int N = 4e4 + 10;
    int len[N << 2], tag[N << 2], mx[N << 2];
    int n, w, h;
    int nums[N], cnt;
    
    void init() {
    	cnt = 0;
    	memset(len, 0, sizeof len);
    	memset(tag, 0, sizeof tag);
    	memset(mx, 0, sizeof mx);
    }
    
    struct line {
    	int l, r, h, tag;
    	bool operator < (const line& b)const {
    		if (h != b.h) return h < b.h;
    		return tag > b.tag;
    	}
    }L[N];
    int ans;
    
    void push_down(int o, int l, int r) {
    	if (!tag[o])return;
    	tag[lo] += tag[o]; tag[ro] += tag[o];
    	mx[lo] += tag[o]; mx[ro] += tag[o];
    	tag[o] = 0;
    }
    void updt(int L, int R, int v, int o = 1, int l = 1, int r = cnt) {
    	if (L <= l and r <= R) {
    		tag[o] += v;
    		mx[o] += v;
    		return;
    	}
    	push_down(o, l, r);
    	if (L <= mid)updt(L, R, v, lo, l, mid);
    	if (R > mid)updt(L, R, v, ro, mid + 1, r);
    	mx[o] = max(mx[lo], mx[ro]);
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("in.txt","r",stdin);
    #endif
    	
    	while (~scanf("%d", &n) and n != -1) {
    		scanf("%d%d", &w, &h);
    		init();
    		for (int i = 1; i <= n; i++) {
    			int x, y; scanf("%d%d", &x, &y);
    			int lx = x - w / 2, rx = x + w / 2;
    			int ly = y - h / 2, ry = y + h / 2;
    			if (w & 1)lx--; if (h & 1)ly--;
    			//printf("%d %d %d %d
    ", lx, ly, rx, ry);
    			nums[++cnt] = lx, nums[++cnt] = rx;
    			L[i * 2 - 1] = { lx,rx,ly,1 };
    			L[i * 2] = { lx,rx,ry,-1 };
    		}
    		sort(L + 1, L + 1 + 2 * n);
    		sort(nums + 1, nums + 1 + cnt);
    		cnt = unique(nums + 1, nums + 1 + cnt) - nums - 1;
    
    		ans = 0;
    		for (int i = 1; i <= 2 * n - 1; i++) {
    			int lid = lower_bound(nums + 1, nums + 1 + cnt, L[i].l) - nums;
    			int rid = lower_bound(nums + 1, nums + 1 + cnt, L[i].r) - nums;
    			//printf("[%d,%d] : %d
    ", lid, rid, L[i].tag);
    			updt(lid, rid, L[i].tag);
    			ans = max(ans, mx[1]);
    		}
    		printf("%d
    ", ans);
    	}
    }
    

    其实跟扫描线没什么关系,就是一个区间修改,区间求最大值的问题

  • 相关阅读:
    nginx通过配置防止DDoS攻击
    BZOJ 2120 数颜色(单点修改莫队)
    数论模板
    BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)
    HDU 4609 3-idiots(FFT)
    BZOJ 3527 [Zjoi2014]力(FFT)
    快速对拍
    HDU 1402 A * B Problem Plus(FFT)
    FFT
    BZOJ 5319: [Jsoi2018]军训列队(可持久化线段树)
  • 原文地址:https://www.cnblogs.com/sduwh/p/14076668.html
Copyright © 2020-2023  润新知