hdu6681 Rikka with Cake【線段樹】【離散化】【2019 Multi-University Training Contest 9】

題意:

在一個封閉的n*m的矩形內,有k條射線,有四個方向,上下左右,射線,射線的端點不重合,該矩形內有多少個封閉的區域
1n,m1e9,1k1e51\le n,m \le 1e9 ,1\le k \le 1e5
沒有任意兩個個端點的x座標 或 y座標相同

題解:

看圖不難觀察到 當橫向的線與縱向的線產生一個交點的時候,封閉的區域就會增加1
於是我們只需要求交點有多少
我的做法是
先離散化x座標和y座標
將所有點按y座標從小到大排序
從小到大,然後對於橫向的線根據方向進行對相應的區間加1 然後對於縱向向下的射線對其所在的x座標,進行單點查詢,我們就可以知道這條縱向的線一共貢獻了多少個交點
再建一次線段樹,從大到小,再進行區間更新,對於縱向向上的射線進行查詢即可
交點的個數爲c,答案就是c+1

AC_code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define maxn 100005
int n, m, k;
struct ss {
	int x, y;
	char fx;
} point[maxn];
bool cmp(ss aa, ss bb) {
	return aa.y < bb.y;
}

/*線段數模板*/

struct node {
	int l,r;
	ll lazy;
} tree[maxn * 4]; // 開四倍大小

void push_up(int root) {
	tree[root].sum = tree[root << 1].sum + tree[(root << 1) | 1].sum;
}   // 兒子的值相加爲父親的值

void push_down(int root) {
void push_down(int root) {
	if(tree[root].lazy) { //有懶惰值
		tree[root << 1].lazy += tree[root].lazy;
		tree[(root << 1) | 1].lazy += tree[root].lazy;//向下傳遞懶惰值
		tree[root << 1].sum += tree[root].lazy * (tree[root << 1].r - tree[root << 1].l + 1);
		tree[(root << 1) | 1].sum += tree[root].lazy * (tree[(root << 1) | 1].r - tree[(root << 1) | 1].l + 1); //根據題目要求處理
		tree[root].lazy = 0;
	}
}

}

void build_tree(int l,int r,int root) {
	tree[root].lazy = 0;
	tree[root].l = l;
	tree[root].r = r;
	if(l == r) {
		tree[root].sum = 0; // 這裏給一個初始值
		return ;
	}
	int mid = (l + r) >> 1;
	build_tree(l,mid,root << 1);
	build_tree(mid + 1,r,(root << 1) | 1);
	push_up(root); //向上更新值
}

void update_interval(int l,int r,int v,int root) { //區間更新
	if(l <= tree[root].l && r >= tree[root].r) {
		tree[root].lazy += v; // 保存懶惰值
		tree[root].sum += v;
		return ;
	}
	if(tree[root].lazy)
		push_down(root);
	int mid = (tree[root].l + tree[root].r) >> 1;
	if(l <= mid)
		update_interval(l,r,v,root << 1);
	if(r > mid)
		update_interval(l,r,v,(root << 1) | 1);
	push_up(root);
}

int query_single(int p,int root) { //單點查詢
	if(tree[root].l == tree[root].r && tree[root].r == p) {
		return tree[root].sum;
	}
	if(tree[root].lazy)
		push_down(root);
	int mid = (tree[root].l + tree[root].r) >> 1;
	if(p <= mid)
		query_single(p,root << 1);
	else
		query_single(p,(root << 1) | 1);
}
int a[maxn], b[maxn];
int main() {
	int t;
	scanf("%d", &t);
	while(t--) {
		int cnta = 0, cntb = 0;
		scanf("%d %d %d", &n, &m, &k);
		for(int i = 0; i < k; i++) {
			scanf("%d %d %c",&point[i].x, &point[i].y, &point[i].fx);
			a[++cnta] = point[i].x;
			b[++cntb] = point[i].y;
		}
		sort(a+1, a+cnta+1);
		sort(b+1, b+cntb+1);
		int lena = unique(a+1, a+cnta+1) - a + 1;
		int lenb = unique(b+1, b+cntb+1) - b + 1;
		for(int i = 0; i < k; i++) {
			point[i].x = lower_bound(a+1, a+cnta+1, point[i].x) - a;
			point[i].y = lower_bound(b+1, b+cntb+1, point[i].y) - b;
		}
		sort(point, point+k, cmp);
		build_tree(0, lena+1, 1);
		ll ans = 1;
		for(int i = 0; i < k; i++) {
			if(point[i].fx == 'L') {
				update_interval(0, point[i].x, 1, 1);
			} else if(point[i].fx == 'R') {
				update_interval(point[i].x, lena+1, 1, 1);
			} else if(point[i].fx == 'D') {
				ans += query_single(point[i].x, 1);
			}
		}
		build_tree(0, lena+1, 1);
		for(int i = k-1; i >= 0; i--) {
			if(point[i].fx == 'L') {
				update_interval(0, point[i].x, 1, 1);
			} else if(point[i].fx == 'R') {
				update_interval(point[i].x, lena+1, 1, 1);
			} else if(point[i].fx == 'U') {
				ans += query_single(point[i].x, 1);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章