[BZOJ1316]点分治关于定长问题的讨论

题目:

我是超链接

题解:

确实是很简单的题目(裸题啊)
在这里讨论一下关于calc的写法

写法1

for (int i=1;i<=m;i++)
    {
        int l=1,r=num,p=r;
        while (l<r)
        {
            while (p>l && deep[p]>=deep[r]) p--;
            p=max(p,l);
            if (deep[l]+deep[r]==q[i])
            {
                ans[i]+=(vv)*(r-p); l++;
            }
            else
            {
                if (deep[l]+deep[r]>q[i]) r=p;else l++;
            }
        }
    }

缺点1:不能统计上q[i]为0的时候,也就是无法单独选一个节点,但这个好办,特判一下就行了
缺点2:当有0权边时不能统计无关于长度的量
这一种写法用在了采药人的路径 这道题,在相同的量很多的情况下不用一个一个加下去,而是固定相同的区间,每次相同的直接加入,是比较好的做法
对于缺点2,“无关于长度的量”指的是Race,这里面统计的是深度,需要进行r的缩小,所以不能使用这种方法
但是在统计有关于长度的量的时候是最快的方法!

写法2

for (int i=1;i<=m;i++)
    {
        int l=1,r=num;
        for (;l<r;l++)
        {
            while (l<r && deep[l]+deep[r]>q[i]) r--;
            for (int j=r;l<j && deep[l]+deep[j]==q[i];j--) ans[i]+=vv;
        }
    }

这种写法同样不能统计上q[i]为0的时候,特判++;
可以使用,在本题上跑了652ms(?),却不清楚为什么跑的快
相比于上一个有优势在于r是-1-1-1的

写法3

for (int i=1;i<=m;i++)
    {
        int l=1,r=num;
        for (;l<=r;l++)//这个等号不能省啊
        {
            while (l<r && deep[l]+deep[r]>q[i]) r--;
            for (int j=r;deep[l]+deep[j]==q[i];j--) ans[i]+=vv;
        }
    }

相当于把重合的部分加了两遍,但是减的时候也是两遍,所以不会出错
而且q[i]为0的时候已经包含进去了!但尽量不要使用,毕竟慢啊。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值