uva 12299 线段树 点相关的操作模板

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=502&page=show_problem&problem=3720

唯一值得一说的就是shift,变成更新点就行

这道题主要是测试下我做的算法模板

先贴模板

/**************************************************************** 2014.4 By Pilgrim  测试数据--uva 12299
 1、注意宏定义
 2、数组a里存储原始数据,从下标1到下标n
 3、使用时先调用build(1,n,1); MAXN是n的上限,在const int调整
 4、稍改动后可用于max,min,sum这些的单点查询,更新
    max:注意build的时候,最初赋为下限
    sum: 注意build的时候,最初赋为上限
    可以在query update 加参数kind,确定是查询max,min,sum,
    从而实现一棵线段树同时多种查询功能
 5、a[],n不可再用
\****************************************************************/

#define lson(i) l , mid , (i)*2
#define rson(i) mid + 1 , r , ((i)*2 +1)
#define ll rt*2
#define rr (rt*2+1)

const int MAXN = 100010;

struct Node{
    int l,r;
    int mmin;
}nodes[MAXN*4];

int a[MAXN],n;

void PushUp(int rt)
{
    nodes[rt].mmin = min(nodes[ll].mmin,nodes[rr].mmin);
}

void Build(int l,int r,int rt)
{
    nodes[rt].l = l;
    nodes[rt].r = r;
    nodes[rt].mmin = MAXN;/*******改***********/
    if(l == r)
    {
        nodes[rt].mmin = a[l];
        return;
    }
    int mid = (l+r)>>1;
    Build(lson(rt));
    Build(rson(rt));
    nodes[rt].mmin = min(nodes[ll].mmin,nodes[rr].mmin);
}

void Update(int rt, int p,int v)/*a[]中下标为p的值改为v*/
{
    if(nodes[rt].l == nodes[rt].r){nodes[rt].mmin = v;return;}
    int mid = (nodes[rt].l+nodes[rt].r)>>1;
    if(p<=mid)
    {
        Update(ll,p,v);
    }
    else
    {
        Update(rr,p,v);
    }
    PushUp(rt);
}

int Query(int l,int r,int rt)
{
    if(l == nodes[rt].l && r == nodes[rt].r)
    {
        return nodes[rt].mmin;
    }
    int mid=(nodes[rt].l+nodes[rt].r)>>1;
    if(r<=mid)
    {
        return Query(l,r,ll);
    }
    else
    {
        if(l>mid)
        {
           return Query(l,r,rr);
        }
        else
        {
           int tmp1 = Query(l,mid,ll);
           int tmp2 = Query(mid+1,r,rr);
           return min(tmp1,tmp2);
        }
    }
}

再贴代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

#define lson(i) l , mid , (i)*2
#define rson(i) mid + 1 , r , ((i)*2 +1)
#define ll rt*2
#define rr (rt*2+1)

const int MAXN = 100010;
const int ORDERSIZE = 35;

struct Node{
    int l,r;
    int mmin;
}nodes[MAXN*4];

int a[MAXN],shift[MAXN];

int n;

void PushUp(int rt)
{
    nodes[rt].mmin = min(nodes[ll].mmin,nodes[rr].mmin);
}

void Build(int l,int r,int rt)
{
    nodes[rt].l = l;
    nodes[rt].r = r;
    nodes[rt].mmin = MAXN;//////////////////////////////////////////////////////////
    if(l == r)
    {
        nodes[rt].mmin = a[l];
        return;

    }
    int mid = (l+r)>>1;
    Build(lson(rt));
    Build(rson(rt));
    nodes[rt].mmin = min(nodes[ll].mmin,nodes[rr].mmin);
}

void Update(int rt, int p,int v)/*下标为p的值改为v*/
{
    if(nodes[rt].l == nodes[rt].r){nodes[rt].mmin = v;return;}
    int mid = (nodes[rt].l+nodes[rt].r)>>1;
    if(p<=mid)
    {
        Update(ll,p,v);
    }
    else
    {
        Update(rr,p,v);
    }
    PushUp(rt);
}

int Query(int l,int r,int rt)
{
    if(l == nodes[rt].l && r == nodes[rt].r)
    {
        return nodes[rt].mmin;
    }
    int mid=(nodes[rt].l+nodes[rt].r)>>1;
    if(r<=mid)
    {
        return Query(l,r,ll);
    }
    else
    {
        if(l>mid)
        {
           return Query(l,r,rr);
        }
        else
        {
           int tmp1 = Query(l,mid,ll);
           int tmp2 = Query(mid+1,r,rr);
           return min(tmp1,tmp2);
        }
    }
}

int main()
{
    int q,t;
    int cnt = 0;/*记录需要移动的数量*/
    char order[51];

    scanf("%d%d",&n,&q);

    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    Build(1,n,1);
    for(int i=0;i<q;i++)
    {
        cnt=0;
        int flag =0;//0表示query,1表示shift
        for(int j=0;1;j++)
        {
            scanf("%c",&order[j]);
            if(order[j] == ‘(‘)
            {
                if(order[j-1] == ‘t‘)
                    flag =1;
                break;
            }
        }
        /*处理输入数据*/
        char c;
        while(scanf("%d%c",&shift[cnt],&c) == 2)cnt++;
        /*做出反应*/
        if(flag)
        {
            for(int j=0;j<cnt-1;j++)
            {
                Update(1,shift[j],a[shift[j+1]]);
            }
            Update(1,shift[cnt-1],a[shift[0]]);
            for(int j=0;j<cnt-1;j++)
            {
                int t = a[shift[j]];
                a[shift[j]]=a[shift[j+1]];
                a[shift[j+1]]=t;
            }
        }
        else
        {
           printf("%d\n",Query(shift[0],shift[1],1));
        }
    }

    return 0;
}

uva 12299 线段树 点相关的操作模板,布布扣,bubuko.com

时间: 2024-08-24 15:18:58

uva 12299 线段树 点相关的操作模板的相关文章

UVa 12299 线段树 单点更新 RMQ with Shifts

因为shift操作中的数不多,所以直接用单点更新模拟一下就好了. 太久不写线段树,手好生啊,不是这错一下就是那错一下. PS:输入写的我有点蛋疼,不知道谁有没有更好的写法. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const

uva 11992 线段树对矩阵进行更新查询

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143 把矩阵变成一行,然后计算位置,lrj给了线段树数组做法 但是我做的线段树空间过大,直接爆掉,所以换方法了 主要还是测试自己的线段树区间更新的模板 各种RE+WA之后AC,,,,, 做的时候出现的几个错误: 1.行和列弄错 2.build初始化的时候,mmin mmax 都初始化为0才对

【hdu5306】Gorgeous Sequence 线段树区间最值操作

题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y$ :求 $[x,y]$ 内所有数的和. 多组测试数据,$\sum n,\sum m\le 10^6$ 题解 线段树区间最值操作 对于线段树上的一个节点,维护对应区间的:最大值 $mx$ .最大值个数 $c$ 及严格次大值 $se$ .那么对于一次区间最小值操作: 如果 $t\ge mx$ ,则这个

线段树(大三的模板)

Up函数 用来更新父亲节点的值 void push(int w) { sum[w] = sum[2*w]+sum[2*w+1];//更新节点值 } 单点更新 先找出第p个数 然后更新他的值 void add(int p,int d,int l,int r,int w) { if(l==r) { sum[w]+=d; return ; } int m = (l+r)/2; if(p<=m) add(p,d,l,m,2*w); else add(p,d,m+1,r,2*w+1); push(w);

线段树一些基本的操作;

更新于2017 4 12 目前学的线段树的操作: 1.某段区间+v: 2.替换某个值(这个代码没涉及0.0) 3.查询区间和,最大值,最小值: 部分代码如下 #include<iostream> #include<cstdio> #include<cstring> #include<cstdio> #inlcude<algorithm> #include<queue> #include<vector> priority_q

uva 11992 线段树

因为行数比较少(最多20),所以可以考虑每行建立一颗线段树进行操作,进而想到可以只建一颗线段树,将矩阵查询变成多次线段查询.另外需要注意的是两种lazy标记的优先级,只要有赋值操作,之前的所有操作都会被替代,所以pushdown的时候要先放下赋值的lazy标记. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF =

HDU4578 线段树(区间更新 + 多种操作)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578  , 线段树的区间更新 + 多种操作,好题. 虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,最后我7.3s很惊险地过了,求大神告知优化方法. 这道题坑在有三种询问:set , add , mul.所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消:当更新mul操作时,如果当前节点add标记存在,就把add标记改为:a

UVa 11992 (线段树 区间修改) Fast Matrix Operations

比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递标记. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxnode = 1 << 17; 7 int _

UVa 1400 (线段树) &quot;Ray, Pass me the dishes!&quot;

求一个区间的最大连续子序列,基本想法就是分治,这段子序列可能在区间的左半边,也可能在区间的右半边,也有可能是横跨区间中点,这样就是左子区间的最大后缀加上右子区间的最大前缀之和. 线段树维护三个信息:区间最大前缀.最大后缀.最大连续子区间的下标. 最大前缀可以通过递推来求:要么是左子区间的最大前缀和.要么是左子区间的和 加上 右子区间的最大前缀和 最大后缀和的递推类似. 递推之前要预处理整个序列的前缀和. 1 #include <cstdio> 2 #include <cstring>