poj3368

本文探讨了线段树的基本概念及其在解决区间查询问题时的优化策略,通过实例展示了如何构建并使用线段树来高效地处理大量数据。文章还讨论了线段树与其他数据结构的对比,强调了其在实际应用中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include<cstdio>
#include<algorithm>

using namespace std;
const int MAX= 100005;
int n,q,li[MAX];
struct Num
{
    int num,st,en,cnt;

}number[MAX],bt[MAX*4];
Num inital(int l,int r,int k)//初始化函数,其实应该算是建树,不过只是一个名字,随便了
{
    if(r-l==1)
      return  bt[k]=number[l];
        Num num1=inital(l,(l+r)/2,k*2+1);
        Num num2=inital((l+r)/2,r,k*2+2);
        if(num1.cnt>num2.cnt)
            return bt[k]=num1;
        else
            return bt[k]=num2;
}
int query(int a,int b,int l,int r,int k)//询问a,b区间的最大值,(l,r)代表当前所在区间,k为所在区间的节点编号
{
    if(l>=a&&r<=b)
        return bt[k].cnt;
    if(r<=a||l>=b)
        return 0;
    return max(query(a,b,l,(l+r)/2,k*2+1),query(a,b,(l+r)/2,r,k*2+2));
}
bool cmp( const Num& t1, const Num& t2 )
{
    return t1.st<=t2.st;

}
int main()
{
    while(cin>>n&&n)
    {
        cin>>q;
        int t,k=0;
        cin>>number[0].num;
        number[0].cnt=1;number[0].st=0;number[0].en=1;
        for(int i=1;i<n;i++)
        {
            scanf("%d",&t);
            if(t==number[k].num)
                {
                    number[k].cnt++;
                    number[k].en++;
                }
                else
                {
                    k++;
                    number[k].num=t;
                    number[k].cnt=1;
                    number[k].st=number[k-1].en;
                    number[k].en=number[k].st+1;
                }
        }
        k++;
        inital(0,k,0);//个人随便写的初始化函数,请勿模仿
        for(int i=0;i<k;i++)//多此一举,本想用stl的,不过当时不知道怎么用在struct中,所以只好这样了
            li[i]=number[i].st;
        for(int i=0;i<q;i++)
        {
            int l,r,ans;
            scanf("%d%d",&l,&r);
            l--;r--;
            int l0=l,r0=r;
            l=upper_bound(li,li+k,l)-li;
            r=upper_bound(li,li+k,r)-li;
            l--,r--;
            if(r-l>0)
            ans=max(r0-number[r].st+1,number[l].en-l0);
            else
                ans=r0-l0+1;//如果都在同一区间,直接求长度
            if(r-l>1)
            ans=max(ans,query(l+1,r,0,k,0));//如果区间跨度太大的话,搜索中间的区间
            printf("%d\n",ans);
        }
    }
    return 0;
}

此题算是一个简单的线段树,但是我因为stl库的问题纠结了半天最后只能无奈这么写了,A完之后看了一下别人的代码发现差异还是有点大的所以也懒得看别人的代码了。

虽是A了,却有很多地方需要改进。不过作为我第一个没有参考模板的线段树,还是挺有成就感的


内容概要:本文档主要展示了C语言中关于字符串处理、指针操作以及动态内存分配的相关代码示例。首先介绍了如何实现键值对(“key=value”)字符串的解析,包括去除多余空格和根据键获取对应值的功能,并提供了相应的测试用例。接着演示了从给定字符串中分离出奇偶位置字符的方法,并将结果分别存储到两个不同的缓冲区中。此外,还探讨了常量(const)修饰符在变量和指针中的应用规则,解释了不同类型指针的区别及其使用场景。最后,详细讲解了如何动态分配二维字符数组,并实现了对这类数组的排序与释放操作。 适合人群:具有C语言基础的程序员或计算机科学相关专业的学生,尤其是那些希望深入理解字符串处理、指针操作以及动态内存管理机制的学习者。 使用场景及目标:①掌握如何高效地解析键值对字符串并去除其中的空白字符;②学会编写能够正确处理奇偶索引字符的函数;③理解const修饰符的作用范围及其对程序逻辑的影响;④熟悉动态分配二维字符数组的技术,并能对其进行有效的排序和清理。 阅读建议:由于本资源涉及较多底层概念和技术细节,建议读者先复习C语言基础知识,特别是指针和内存管理部分。在学习过程中,可以尝试动手编写类似的代码片段,以便更好地理解和掌握文中所介绍的各种技巧。同时,注意观察代码注释,它们对于理解复杂逻辑非常有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值