UOJ#406/LOJ2864【IOI2018】排座位 线段树

版权声明:本文是蒟蒻写的,转载。。。随便吧 https://blog.csdn.net/xgc_woker/article/details/87120606

Description
你要在一个长方形大厅里举办国际编程比赛,该大厅共有 H W HW 个座位( H H W W 列)。行的编号是从 0 0 H 1 H-1 ,列的编号是从 0 0 W 1 W-1 。位于 r r c c 列的座位用 ( r , c ) (r,c) 表示。一共邀请了 H W HW 位参赛者,编号是从 0 0 H W 1 HW-1 。你制定好了一个座位表,第 i i 0 i H W 1 0\le i\le HW-1 )个参赛者被安排到座位 ( R i , C i ) (R_i,C_i) 。座位表中参赛者和座位是一一对应的。
大厅中一个座位集合 S S 被称为是长方形的,如果存在整数 r 1 , r 2 , c 1 r_1,r_2,c_1 c 2 c_2 满足下列条件:
0 r 1 r 2 H 1 0\le r_1\le r_2\le H-1
0 c 1 c 2 W 1 0\le c_1\le c_2\le W-1
S S 正好是所有满足 r 1 r r 2 r_1\le r\le r_2 c 1 c c 2 c_1\le c\le c_2 的座位 ( r , c ) (r,c) 的集合。
如果一个长方形座位集合包含 k k 1 k H W 1\le k\le HW )个座位,并且被分配到这个集合的参赛者的编号恰好是从 0 0 k 1 k-1 ,那么该集合是美妙的。一个座位表的美妙度定义为这个表中美妙的长方形座位集合的个数。
在准备好座位表后,你会收到一些交换两个参赛者座位的请求。具体来说,有 Q Q 个这样的请求,按时间顺序编号为 0 0 Q 1 Q-1 。第 j j 0 j Q 1 0\le j\le Q-1 )个请求希望交换参赛者 A j A_j B j B_j 的座位。你立即接受每个请求并更新座位表。每次更新后,你的目标是计算当前座位表的美妙度。


Sample Input
2 3 2
0 0
1 0
1 1
0 1
0 2
1 2
0 5
0 5


Sample Output
3
4


对于一个 k k ,我们将小于等于 k k 的值染成黑色,大于 k k 的值染成白色,那么就是询问有多少个 k k 满足构成了一个矩阵,且所有黑色构成了一个联通块。
对于构成了一个连通块就是相当于只存在一个黑点,它的左边和上边都是白点。
对于构成了矩阵,就是相当于不存在一个白点,它的上下左右的黑点数是两个以上。
第一种点的个数不会小于 1 1 个,第二种点的个数不会小于 0 0 个,那么只用看加起来是否等于 1 1 即可。
这个东西你就相当于用线段树维护一个最小值以及最小值出现的次数。
每次的修改是常数次的(好像修改次数还挺多的,有十多次吧。。。


#include "seats.h"
#include <ctime>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;
typedef long long LL;
int _max(int x, int y) {return x > y ? x : y;}
int _min(int x, int y) {return x < y ? x : y;}
const int N = 1000001;
const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {-1, 0, 1, 0};
int read() {
	int s = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * f;
}
void put(int x) {
	if(x >= 10) put(x / 10);
	putchar(x % 10 + '0');
}

struct tnode {
	int lc, rc, c, s, lazy;
} t[N * 2]; int cnt;
int n, m, g[N], R[N], C[N];
bool v[N];

void bt(int l, int r) {
	int now = ++cnt;
	t[now].lc = t[now].rc = -1;
	t[now].c = 0, t[now].s = (r - l + 1);
	t[now].lazy = 0;
	if(l < r) {
		int mid = (l + r) / 2;
		t[now].lc = cnt + 1; bt(l, mid);
		t[now].rc = cnt + 1; bt(mid + 1, r);
	}
}

void pushdown(int now) {
	if(!t[now].lazy) return ;
	int lc = t[now].lc, rc = t[now].rc;
	t[lc].c += t[now].lazy, t[lc].lazy += t[now].lazy;
	t[rc].c += t[now].lazy, t[rc].lazy += t[now].lazy;
	t[now].lazy = 0;
}

void update(int now) {
	int lc = t[now].lc, rc = t[now].rc;
	if(t[lc].c == t[rc].c) t[now].c = t[lc].c, t[now].s = t[lc].s + t[rc].s;
	else if(t[lc].c < t[rc].c) t[now].c = t[lc].c, t[now].s = t[lc].s;
	else t[now].c = t[rc].c, t[now].s = t[rc].s;
}

void change(int now, int l, int r, int ll, int rr, int c) {
	if(l == ll && r == rr) {t[now].c += c, t[now].lazy += c; return ;}
	pushdown(now);
	int mid = (l + r) / 2;
	if(rr <= mid) change(t[now].lc, l, mid, ll, rr, c);
	else if(ll > mid) change(t[now].rc, mid + 1, r, ll, rr, c);
	else change(t[now].lc, l, mid, ll, mid, c), change(t[now].rc, mid + 1, r, mid + 1, rr, c);
	update(now);
}

void cc(int x, int y, int c) {
	if(x < 0 || y < 0 || x >= n || y >= m || v[x * m + y]) return ;
	v[x * m + y] = 1;
	int m1 = n * m, m2 = n * m;
	for(int k = 0; k < 2; k++) {
		int nx = x + dx[k], ny = y + dy[k];
		if(nx < 0 || ny < 0);
		else {
			if(g[nx * m + ny] < m1) m2 = m1, m1 = g[nx * m + ny];
			else if(g[nx * m + ny] < m2) m2 = g[nx * m + ny];
		}
	} if(m1 > g[x * m + y]) change(1, 1, n * m, g[x * m + y] + 1, m1, c);
	for(int k = 2; k < 4; k++) {
		int nx = x + dx[k], ny = y + dy[k];
		if(nx >= n || ny >= m);
		else {
			if(g[nx * m + ny] < m1) m2 = m1, m1 = g[nx * m + ny];
			else if(g[nx * m + ny] < m2) m2 = g[nx * m + ny];
		}
	} if(m2 < g[x * m + y]) change(1, 1, n * m, m2 + 1, g[x * m + y], c);
}

void clear(int x, int y) {
	v[x * m + y] = 0;
	for(int k = 0; k < 4; k++) {
		int nx = x + dx[k], ny = y + dy[k];
		if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
		v[nx * m + ny] = 0;
	}
}

void give_initial_chart(int h, int w, vector<int>_r, vector<int>_c) {
	n = h, m = w;
	for(int i = 0; i < n * m; i++) {
		R[i] = _r[i], C[i] = _c[i];
		g[R[i] * m + C[i]] = i;
	} bt(1, n * m);
	for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) cc(i, j, 1);
	memset(v, 0, sizeof(v));
}

int swap_seats(int a, int b) {
	int ax = R[a], ay = C[a];
	int bx = R[b], by = C[b];
	clear(ax, ay), clear(bx, by);
	cc(ax, ay, -1), cc(bx, by, -1);
	for(int k = 0; k < 4; k++) cc(ax + dx[k], ay + dy[k], -1);
	for(int k = 0; k < 4; k++) cc(bx + dx[k], by + dy[k], -1);
	swap(g[ax * m + ay], g[bx * m + by]);
	swap(R[a], R[b]), swap(C[a], C[b]);
	clear(ax, ay), clear(bx, by);
	cc(ax, ay, 1), cc(bx, by, 1);
	for(int k = 0; k < 4; k++) cc(ax + dx[k], ay + dy[k], 1);
	for(int k = 0; k < 4; k++) cc(bx + dx[k], by + dy[k], 1);
	if(t[1].c == 1) return t[1].s;
	else return 0;
}

猜你喜欢

转载自blog.csdn.net/xgc_woker/article/details/87120606