zoukankan      html  css  js  c++  java
  • [IOI2018] seats 排座位(线段树)

    Solution

    • 显然同样大小的子矩阵中,符合条件的最多一个
    • 考虑判断\([0...i-1]\)的数是否构成一个矩形:
    • \([0...i-1]\)所在格点染成黑色,剩下的染成白色
    • 将边界以外的格点看作白色
    • 如果\([0...i-1]\)的数是否构成一个矩形,那么这\(i\)个点中:
    • \((1)\) “左上都是白点”的黑点数记为\(x\)\(x=1\)
    • \((2)\) “上下左右4个点中,是黑点的大于等于2个”的白点记为\(y\)\(y=0\)
    • 满足\((1)\),就满足了这\(i\)个点处于同一连通块
    • 满足\((2)\),就满足了这\(i\)个点构成一个矩形,不满足则说明存在“拐角”,例如(下图中\(B\)为满足\((2)\)的白点):
      \(WB\)
      \(WW\)
    • 如果只满足\((2)\),不满足\((1)\),可能构成多个矩形
    • 因为不存在\(x=0\)\(y=1\)的情况(实际上是没有\(x=0\)的情况)
    • 所以满足\(x+y=1\)即合法
    • 线段树维护对于每个\(i\)\(x+y\)的值
    • 并且维护区间最小值及最小值个数(最小值不可能为0)
    • 对于每个点\(u\),一定是先白后黑
    • \(u\)为白点的最晚时刻为\(l[u]\),为黑点的最早时刻为\(r[u]\)
    • \(u\)周围\(4\)个点的\(r\)次小值\(z\)(如果点越界,\(r=inf\)
    • 它作为满足\((2)\)的点的时段即\([z,l[u]]\)(注意特判\(z>l[u]\)的情况)
    • 那么在线段树上给\([z,l[u]]+1\)
    • \(u\)左上的\(l\)的最小值为\(t\)(如果点越界,\(l=HW-1\)
    • 它作为满足\((1)\)的点的时段即\([r[u],t]\)(注意特判\(r[u]>t\)的情况)
    • 那么在线段树上给\([r[u],t]+1\)
    • 每次交换时,见掉两个点\(a,b\)及他们周围\(4\)个点(共\(O(10)\)个点)在两点交换前的贡献,交换\(a,b\),加上这些点在两点交换后的贡献
    • 注意如果\(10\)个点中有重复的,不可以重复加减贡献
    • 要记录矩阵中每个位置上的数是什么,以及每个数所在位置是什么

    Code

    注:由于个人习惯,以下程序中编号为\([1...HW]\)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define p2 p << 1
    #define p3 p << 1 | 1
    
    template <class t>
    inline void read(t & res)
    {
    	char ch;
    	while (ch = getchar(), !isdigit(ch));
    	res = ch ^ 48;
    	while (ch = getchar(), isdigit(ch))
    	res = res * 10 + (ch ^ 48);
    }
    
    const int e = 1e6 + 5, dx[] = {-1, 0, 1, 0, 0}, dy[] = {0, -1, 0, 1, 0}, inf = 0x3f3f3f3f;
    struct point
    {
    	int x, y;
    }a[e];
    int val[e * 4], cnt[e * 4], n, m, add[e * 4], q, tmp, id[e], pos[e], vis[e], now;
    
    inline void collect(int p)
    {
    	if (val[p2] == val[p3])
    	{
    		val[p] = val[p2];
    		cnt[p] = cnt[p2] + cnt[p3];
    	}
    	else if (val[p2] < val[p3])
    	{
    		val[p] = val[p2];
    		cnt[p] = cnt[p2];
    	}
    	else
    	{
    		val[p] = val[p3];
    		cnt[p] = cnt[p3];
    	}
    }
    
    inline void pushdown(int p)
    {
    	if (add[p])
    	{
    		add[p2] += add[p];
    		add[p3] += add[p];
    		val[p2] += add[p];
    		val[p3] += add[p];
    		add[p] = 0;
    	}
    }
    
    inline void build(int l, int r, int p)
    {
    	if (l == r)
    	{
    		cnt[p] = 1;
    		return;
    	}
    	int mid = l + r >> 1;
    	build(l, mid, p2);
    	build(mid + 1, r, p3);
    	collect(p);
    }
    
    inline void update(int l, int r, int s, int t, int v, int p)
    {
    	if (l == s && r == t)
    	{
    		val[p] += v;
    		add[p] += v;
    		return; 
    	}
    	pushdown(p);
    	int mid = l + r >> 1;
    	if (t <= mid) update(l, mid, s, t, v, p2);
    	else if (s > mid) update(mid + 1, r, s, t, v, p3);
    	else
    	{
    		update(l, mid, s, mid, v, p2);
    		update(mid + 1, r, mid + 1, t, v, p3);
    	}
    	collect(p);
    }
    
    inline void upt(int l, int r, int v)
    {
    	l = max(l, 1);
    	r = min(r, tmp);
    	update(1, tmp, l, r, v, 1);
    }
    
    inline int get(int x, int y)
    {
    	return (x - 1) * m + y;
    }
    
    inline void join(int x, int y, int opt)
    {
    	vis[get(x, y)] = now;
    	int i, p[4];
    	for (i = 0; i < 4; i++)
    	{
    		int xx = dx[i] + x, yy = dy[i] + y;
    		if (xx < 1 || yy < 1 || xx > n || yy > m) p[i] = inf;
    		else p[i] = id[get(xx, yy)];
    	}
    	sort(p, p + 4);
    	int tim = id[get(x, y)] - 1;
    	if (p[1] <= tim) upt(p[1], tim, opt);
    	tim++;
    	for (i = 0; i < 2; i++)
    	{
    		int xx = dx[i] + x, yy = dy[i] + y;
    		if (xx < 1 || yy < 1 || xx > n || yy > m) p[i] = inf;
    		else p[i] = id[get(xx, yy)] - 1;
    	}
    	sort(p, p + 2);
    	if (tim <= p[0]) upt(tim, p[0], opt);
    }
    
    inline void change(int x, int y, int opt)
    {
    	int i;
    	for (i = 0; i < 5; i++)
    	{
    		int xx = x + dx[i], yy = y + dy[i];
    		if (xx < 1 || yy < 1 || xx > n || yy > m || vis[get(xx, yy)] == now) continue;
    		join(xx, yy, opt);
    	}
    }
    
    int main()
    {
    	read(n); read(m); read(q);
    	int i, u, v;
    	tmp = n * m;
    	for (i = 1; i <= tmp; i++)
    	{
    		read(a[i].x);
    		a[i].x++;
    		read(a[i].y);
    		a[i].y++;
    		pos[i] = get(a[i].x, a[i].y);
    		id[get(a[i].x, a[i].y)] = i;
    	}
    	build(1, tmp, 1);
    	for (i = 1; i <= tmp; i++) join(a[i].x, a[i].y, 1);
    	while (q--)
    	{
    		read(u);
    		read(v);
    		u++;
    		v++;
    		now++;
    		change(a[u].x, a[u].y, -1);
    		change(a[v].x, a[v].y, -1);
    		int idx = u, idy = v, px = pos[idx],
    		py = pos[idy];
    		id[px] = idy;
    		id[py] = idx;
    		pos[idx] = py;
    		pos[idy] = px;
    		now++;
    		change(a[u].x, a[u].y, 1);
    		change(a[v].x, a[v].y, 1);
    		swap(a[u].x, a[v].x);
    		swap(a[u].y, a[v].y);
    		printf("%d\n", cnt[1]);
    	}
    	return 0; 
    }
    
  • 相关阅读:
    在TreeView控件节点中显示图片
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1145 Hashing
    PAT 甲级 1145 Hashing
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1149 Dangerous Goods Packaging
  • 原文地址:https://www.cnblogs.com/cyf32768/p/12196341.html
Copyright © 2011-2022 走看看