zoukankan      html  css  js  c++  java
  • 【JZOJ6308】中间值【分治】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/6308
    在这里插入图片描述


    思路:

    把求中间值转换成求两个区间的第kk小。
    对于两个区间[l1,r1][l2,r2][l_1,r_1][l_2,r_2],我们把kk拆分成两半midmidmid=k2mid=frac{k}{2}),然后比较两个区间的第midmid大。如果第一个区间的第midmid大会更大,那么第二个区间的[l2,mid][l_2,mid]都不可能是原区间的第kk小,且一定小于第kk小,所以直接把区间缩小为[l1,r1][mid+1,r2][l_1,r_1][mid+1,r_2],然后kk减去该区间长度即可。
    这样kk每次会减去一半,时间复杂度O(nlogn)O(nlog n)


    代码:

    #include <cstdio>
    #include <string>
    using namespace std;
    
    const int N=500010;
    int n,m,opt,len,a[N],b[N];
    
    int read()
    {
    	int d=0; char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch))
    		d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    int solve(int l1,int r1,int l2,int r2,int k)
    {
    	if (l1>r1) return b[l2+k-1];
    	if (l2>r2) return a[l1+k-1];
    	if (k==1) return min(a[l1],b[l2]);
    	int mid1=min(l1+k/2-1,r1),mid2=min(l2+k/2-1,r2);
    	if (a[mid1]<b[mid2]) return solve(mid1+1,r1,l2,r2,k-(mid1+1-l1));
    		else return solve(l1,r1,mid2+1,r2,k-(mid2+1-l2));
    }
    
    int main()
    {
    	freopen("median.in","r",stdin);
    	freopen("median.out","w",stdout);
    	n=read(); m=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	for (int i=1;i<=n;i++) b[i]=read();
    	while (m--)
    	{
    		opt=read();
    		if (opt==1)
    		{
    			int x=read(),y=read(),z=read();
    			if (!x) a[y]=z;
    				else b[y]=z;
    		}
    		else
    		{
    			int l1=read(),r1=read(),l2=read(),r2=read();
    			len=r1-l1+r2-l2+2;
    			printf("%d
    ",solve(l1,r1,l2,r2,len/2+1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    VS2017专业版和企业版激活密钥
    RabbitMQ卸载重新安装
    RabbitMQ-基本命令操作
    天猫
    铜氨纤维
    四肢很发达,头脑不简单
    运动可以健身健脑
    1 职业天花板来自认识的局限性
    天猫-服饰行业标准
    服装设计都是需要什么
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998051.html
Copyright © 2011-2022 走看看