zoukankan      html  css  js  c++  java
  • jzoj 6308. 中间值

    Description

    详见OJ

    Solution

    考场先想到(O(nlog^2n))的线段树,发现过不了。于是开始“异想天开”。
    最后神奇想到分块。
    我们对于(a[])维护一个(to[i])
    (to[i])表示(a[i]>=b[j])的最大的(j)
    维护时用分块来标记防止修改的区间太大。
    赛后同学说分块是(O(m根号n))的,我才发现时间好像过不了。。。
    但我好像没有一个点(TLE)。。。
    不停改细节最后成功(AC)(700+ms)没有卡线。
    分块打法好!

    Code

    (分块)

    #include <cstdio>
    #include <cmath>
    #define N 500010
    #define mem(x, a) memset(x, a, sizeof x)
    #define fo(x, a, b) for (int x = a; x <= b; x++)
    #define fd(x, a, b) for (int x = a; x >= b; x--)
    using namespace std;
    int n, m, a[N], b[N], to[N], now = 0;
    int bl[N], val[N], st, zuo[N], you[N];
    bool bz[N];
    
    inline int read()
    {
    	int x = 0; char c = getchar();
    	while (c < '0' || c > '9') c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return x;
    }
    
    inline int max(int x, int y) {return x > y ? x : y;}
    
    inline int solve(int x) {return bz[bl[x]] ? val[bl[x]] : to[x];}
    
    void gave(int x)
    {
    	if (! bz[x]) return;
    	fo(i, zuo[x], you[x]) to[i] = val[x];
    	bz[x] = 0;
    }
    
    int main()
    {
    	freopen("median.in", "r", stdin);
    	freopen("median.out", "w", stdout);
    	n = read(), m = read(); st = sqrt(n);
    	fo(i, 1, n)
    	{
    		a[i] = read();
    		bl[i] = (i - 1) / st + 1;
    		if (! zuo[bl[i]]) zuo[bl[i]] = i;
    		you[bl[i]] = i;
    	}
    	fo(i, 1, n) b[i] = read();
    	fo(i, 1, n)
    	{
    		while (now < n && a[i] >= b[now + 1]) now++;
    		to[i] = now;
    	}
    	to[0] = 0, to[n + 1] = n;
    	while (m--)
    	{
    		int opt = read();
    		if (opt == 1)
    		{
    			int x = read(), y = read(), z = read();
    			if (x == 0)
    			{
    				int l = solve(y - 1), r = solve(y + 1), mid;
    				while (l <= r)
    				{
    					mid = l + r >> 1;
    					if (z >= b[mid]) l = mid + 1;
    					else r = mid - 1;
    				}
    				a[y] = z;
    				if (solve(y) != l - 1)
    					to[y] = l - 1, bz[bl[y]] = 0;
    			}
    			else
    			{
    				int l = 1, r = n, mid, le, ri;
    				while (l <= r)
    				{
    					mid = l + r >> 1;
    					if (a[mid] >= b[y - 1]) r = mid - 1;
    					else l = mid + 1;
    				}
    				le = r + 1;
    				l = r, r = n;
    				while (l <= r)
    				{
    					mid = l + r >> 1;
    					if (a[mid] < b[y + 1]) l = mid + 1;
    					else r = mid - 1;
    				}
    				ri = l - 1;
    				l = le, r = ri;
    				while (l <= r)
    				{
    					mid = l + r >> 1;
    					if (a[mid] >= z) r = mid - 1;
    					else l = mid + 1;
    				}
    				if (le <= r)
    				{
    					if (bl[le] == bl[r])
    					{
    						gave(bl[le]);
    						fo(i, le, r) to[i] = y - 1;
    					}
    					else
    					{
    						fo(i, bl[le] + 1, bl[r] - 1)
    							bz[i] = 1, val[i] = y - 1;
    						gave(bl[le]);
    						fo(i, le, you[bl[le]]) to[i] = y - 1;
    						gave(bl[r]);
    						fo(i, zuo[bl[r]], r) to[i] = y - 1;
    					}
    				}
    				r++;
    				if (r <= ri)
    				{
    					if (bl[r] == bl[ri])
    					{
    						gave(bl[r]);
    						fo(i, r, ri) to[i] = y;
    					}
    					else
    					{
    						fo(i, bl[r] + 1, bl[ri] - 1)
    							bz[i] = 1, val[i] = y;
    						gave(bl[r]);
    						fo(i, r, you[bl[r]]) to[i] = y;
    						gave(bl[ri]);
    						fo(i, zuo[bl[ri]], ri) to[i] = y;
    					}
    				}
    				b[y] = z;
    			}
    		}
    		else
    		{
    			int l1 = read(), r1 = read(), l2 = read(), r2 = read();
    			int sum = (r1 - l1 + 1 + r2 - l2 + 1) / 2 + 1;
    			if (a[r1] <= b[l2])
    			{
    				if (r1 - l1 + 1 >= sum) printf("%d
    ", a[l1 + sum - 1]);
    				else printf("%d
    ", b[l2 + sum - (r1 - l1 + 1) - 1]);
    			}
    			else if (a[l1] >= b[r2])
    			{
    				if (r2 - l2 + 1 >= sum) printf("%d
    ", b[l2 + sum - 1]);
    				else printf("%d
    ", a[l1 + sum - (r2 - l2 + 1) - 1]);
    			}
    			else
    			{
    				int l = l1, r = r1, mid, num;
    				while (l <= r)
    				{
    					mid = l + r >> 1;
    					num = mid - l1 + 1;
    					if (solve(mid) > r2) num += r2 - l2 + 1;
    					else if (solve(mid) >= l2) num += solve(mid) - l2 + 1;
    					if (num == sum) {r = mid - 1; break;}
    					else if (num >= sum) r = mid - 1;
    					else l = mid + 1;
    				}
    				r++;
    				num = r - l1 + 1;
    				if (solve(r) > r2) num += r2 - l2 + 1;
    				else if (solve(r) >= l2) num += solve(r) - l2 + 1;
    				if (r <= r1 && num == sum) printf("%d
    ", a[r]);
    				else printf("%d
    ", b[l2 + sum - (r - l1 + 1)]);
    			}
    		}
    	}
    	return 0;
    }
    

    不过,听完讲后,发现这题分治做起来好容易啊。

    转载需注明出处。
  • 相关阅读:
    Clion 配置
    JetBrains 全套激活 Pycharm Clion 高校学生老师免费用
    VS Code 搭建 C/C++ 编译运行环境的四种方案 (待完善)
    专治编译器编辑器vscode中文乱码输出 win10 配置系统默认utf-8编码
    AlexeyAB大神版yolo 待完善
    Python 的 GUI 开发工具
    Python打包—Pyinstaller
    pip freeze 打包依赖库及setup.py
    jenkins中布置python测试
    在Ubuntu上安装Jenkins
  • 原文地址:https://www.cnblogs.com/jz929/p/11372844.html
Copyright © 2011-2022 走看看