具有惰性传播的线段树时间限制问题

发布于 2024-11-18 02:13:47 字数 2211 浏览 2 评论 0原文

以下是http://www.spoj.pl/problems/LITE/的实现使用线段树进行延迟传播。我是分割树的新手,我不明白为什么我会得到 TLE。有人可以看一下并帮助我纠正我的错误吗?

#include <iostream>
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAX 100000
using namespace std;
int M[2*MAX+1];
int flag[2*MAX+1];
int count;
void refresh(int begin,int end,int n)
{
    M[n] = end-begin+1 - M[n];
    flag[n]=0;
    flag[n*2] =!flag[n*2];
    flag[n*2+1] =!flag[n*2+1];
}
void update(int begin,int end,int i,int j,int n=1)
{
    if(flag[n])
    {
        refresh(begin,end,n);
    }
    if(begin>=i && end<=j)
    {
        if(!flag[n])
        {
            refresh(begin,end,n);
        }
        flag[n] = 0;
        return;
    }
    else if(begin>=end)
    {
        return;
    }
    else
    {
        int mid = (begin+end)>>1;
        if(i<=mid)
        {
            update(begin,mid,i,j,n*2);
        }
        if(j>mid)
        {
            update(mid+1,end,i,j,n*2+1);
        }
        if(flag[2*n])
        {
            refresh(begin,mid,2*n);
        }
        if(flag[2*n+1])
        {
            refresh(mid+1,end,2*n+1);
        }
        M[n] = M[n*2]+ M[n*2+1];
    }
}
int query(int begin,int end,int i,int j,int n=1)
{
    if(flag[n])
    {
        refresh(begin,end,n);
    }
    if(begin>=i && end<=j)
    {
        return M[n];
    }
    if(begin>=end)
    {
        return 0;
    }
    int mid = (begin+end)>>1;
    int l=0,r=0;
    if(i<=mid)
    {
        l = query(begin,mid,i,j,n*2);
    }
    if(j>mid)
    {
        r = query(mid+1,end,i,j,n*2+1);
    }
    if(flag[2*n])
    {
        refresh(begin,mid,2*n);
    }
    if(flag[2*n+1])
    {
        refresh(mid+1,end,2*n+1);
    }
    M[n] = M[n*2]+ M[n*2+1];
    return l+r;
}
int main()
{
    memset(M,0,sizeof M);
    int n,m,a,b,c;
    scanf("%d%d",&n,&m);
    for(int i=0; i<m; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(a==0)
        {
            update(1,n,b,c);
        }
        else
        {
            printf("%d\n",query(1,n,b,c));
        }
    }
    return 0;
}

The following is the implementation of http://www.spoj.pl/problems/LITE/ using Segment Tree's with lazy propagation. I am new to segment trees and I cannot understand why I am getting TLE. Could someone please look at it and help me correct my error?

#include <iostream>
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAX 100000
using namespace std;
int M[2*MAX+1];
int flag[2*MAX+1];
int count;
void refresh(int begin,int end,int n)
{
    M[n] = end-begin+1 - M[n];
    flag[n]=0;
    flag[n*2] =!flag[n*2];
    flag[n*2+1] =!flag[n*2+1];
}
void update(int begin,int end,int i,int j,int n=1)
{
    if(flag[n])
    {
        refresh(begin,end,n);
    }
    if(begin>=i && end<=j)
    {
        if(!flag[n])
        {
            refresh(begin,end,n);
        }
        flag[n] = 0;
        return;
    }
    else if(begin>=end)
    {
        return;
    }
    else
    {
        int mid = (begin+end)>>1;
        if(i<=mid)
        {
            update(begin,mid,i,j,n*2);
        }
        if(j>mid)
        {
            update(mid+1,end,i,j,n*2+1);
        }
        if(flag[2*n])
        {
            refresh(begin,mid,2*n);
        }
        if(flag[2*n+1])
        {
            refresh(mid+1,end,2*n+1);
        }
        M[n] = M[n*2]+ M[n*2+1];
    }
}
int query(int begin,int end,int i,int j,int n=1)
{
    if(flag[n])
    {
        refresh(begin,end,n);
    }
    if(begin>=i && end<=j)
    {
        return M[n];
    }
    if(begin>=end)
    {
        return 0;
    }
    int mid = (begin+end)>>1;
    int l=0,r=0;
    if(i<=mid)
    {
        l = query(begin,mid,i,j,n*2);
    }
    if(j>mid)
    {
        r = query(mid+1,end,i,j,n*2+1);
    }
    if(flag[2*n])
    {
        refresh(begin,mid,2*n);
    }
    if(flag[2*n+1])
    {
        refresh(mid+1,end,2*n+1);
    }
    M[n] = M[n*2]+ M[n*2+1];
    return l+r;
}
int main()
{
    memset(M,0,sizeof M);
    int n,m,a,b,c;
    scanf("%d%d",&n,&m);
    for(int i=0; i<m; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(a==0)
        {
            update(1,n,b,c);
        }
        else
        {
            printf("%d\n",query(1,n,b,c));
        }
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

携君以终年 2024-11-25 02:13:47

M[node]^=1; 可能比 M[node] = (M[node]==0)?1:0;更快(begin+end)>>1(begin/end)/2 更快,但不是很相关

LE:尝试内联递归函数是否会运行得更快。我认为它多次解开了递归并且运行得更快一些。也许发送参数作为参考会让它运行得更快,试试吧。如果正确选择了测试用例,您仍然不应该能够通过这种技巧来通过测试,但有时它会有所帮助。

M[node]^=1; might be faster than M[node] = (M[node]==0)?1:0;, and (begin+end)>>1 faster than (begin/end)/2, but not very relevant

LE: Try if making the recursive functions inline will run faster. I think it unravels the recursion a couple of times and works a little bit faster. Maybe sending the parameters as references will make it run faster, try that out. If the test cases are chosen properly you still shouldn't be able to pass the tests with this trickery, but it helps sometimes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文