zoukankan      html  css  js  c++  java
  • 魔性の分块 | | jzoj1243 | | 线段树の暴力

    题目的打开方式是酱紫的

    然而作为一只蒻蒟根本不会线段树该怎么办呢?

    sro  MZX  orz 是这样说的:用分块啊!

    分块

    根据紫萱学姐的教程,分块的打开姿势是这样的:

    我们要对一个数组进行整体操作,那么我们就可以把他们分成元素相等的n部分,由于n部分的最大值很容易找,也就是我们可以预处理出最大值(更何况此题最开始数组赋初值为0)我们要查询第k1-k2个数的最大值,就返回k1-k2所对应的块的最大值即可,

    好,作为一只蒻蒟根本不知所云?

    用一张图解来表示一下就是酱紫

    红线代表整个数组,底下数轴就代表每一块的大小,绿线表示查询的区间,蓝线和橙线代表块里的其他元素;

    那么左端点块内剩余的元素该怎么找呢?

    这时候我们可以模拟出来一个小块,这个小块代表剩余元素的最大值,然后再和其他元素块的最大值就可以了,同理右端点也是如此;

    那么代码实现呢?

      

    代码

    莫名其妙刚开始只能过小数据,我也不知道为什么,后来经过神犇lyy的点拨,我才知道是什么意思

    (一)插入

    v-1.0的代码如下

    int tempx=x/S;
        int left=tempx*S,right=min(left+S,n);
        a[x]=y;
        for(int i=left;i<right;i++)
            if(a[i]>block[tempx])
                block[tempx]=a[i];
    

    v2.0的代码如下

    int tempx=x/S;
        int left=tempx*S,right=min(left+S,n);//注意right的取值
        a[x]=y;
        block[tempx]=-1*INF;
        for(int i=left;i<right;i++)
            if(a[i]>block[tempx])
                block[tempx]=a[i];
    

     没错只有一步tempx的初值还要变化成最小值,并且要注意right中left+S不能超过n的取值范围

    (二) 查询

    int work(int x,int y)
    {
    	int l=x/S,r=y/S,ans=-INF;//定位块
    	if(l==r)
        {//如果在一块内
    		for(int i=x;i<=y;i++)
    			if(a[i]>ans)
    				ans=a[i];
    		return ans;
    	}
    	for(int i=x,ed=(l+1)*S;i<ed;i++)
    		if(a[i]>ans)
    			ans=a[i];
    	for(int i=l+1;i<r;i++)
    		if(block[i]>ans)//整体操作
    			ans=block[i];
    	for(int i=r*S;i<=y;i++)
    		if(a[i]>ans)
    			ans=a[i];
    	return ans;
    }
    

      

  • 相关阅读:
    What is the purpose of FormsAuthenticationTicket isPersistent property?
    Forms Authentication configurations
    What is the difference between localStorage, sessionStorage, session and cookies?
    Set-Cookie
    申威机器信息
    systemctl 关闭图形界面的办法
    sourcetree 使用
    在 Web 项目中应用 Apache Shiro
    移动web开发框架
    从0开始搭建symphony
  • 原文地址:https://www.cnblogs.com/supersumax/p/5980089.html
Copyright © 2011-2022 走看看