zoukankan      html  css  js  c++  java
  • 线段树无止尽版

    最近在陆陆续续学习线段树  把学习的点滴汇集起来 也许将来对自己和别人都有所帮助!!

    首先特别鸣谢NotOnlySuccess (http://www.notonlysuccess.com/?p=978) 我视这位神明为线段树的导师 他的【完全版】造福全人类

    Hdu1754 I hate it

    单点更新:最最基础的线段树,只更新叶子节点,然后把信息用PushUP(int r)这个函数更新上来

    View Code
    #include<iostream>
    #include
    <algorithm>
    using namespace std;
    int MAXN[4000001],d[4000001];
    void PushUp(int rt)
    {
    MAXN[rt]
    =max(MAXN[rt<<1],MAXN[rt<<1|1]);
    }
    void build(int l,int r,int rt)
    {
    if(l==r)
    {
    cin
    >> MAXN[rt];
    return;
    }
    int m=(l+r)>>1;
    build(l,m,rt
    <<1);
    build(m
    +1,r,(rt<<1)+1);
    PushUp(rt);
    }
    void update(int p,int sc,int l,int r,int rt)
    {
    if(l==r)
    {
    MAXN[rt]
    =sc;
    return;
    }
    int m=(l+r)>>1;
    if(p<=m)update(p,sc,l,m,rt<<1);
    else update(p,sc,m+1,r,(rt<<1)+1);
    PushUp(rt);
    }
    int getmax(int L,int R,int l,int r,int rt)
    {
    if(L<=l&&r<=R)
    {
    return MAXN[rt];
    }
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)ret=max(ret,getmax(L,R,l,m,rt<<1));
    if(R>m)ret=max(ret,getmax(L,R,m+1,r,(rt<<1)+1));
    return ret;
    }
    int main()
    {
    int n,m,a,b;
    char ch;
    while(cin>>n>>m)
    {
    build(
    1,n,1);
    for(int i=0;i<m;i++)
    {
    cin
    >>ch>>a>>b;
    if(ch=='U')update(a,b,1,n,1);
    else cout<<getmax(a,b,1,n,1)<<endl;
    }
    }
    }

    /*hdu4027Can you answer these queries线段树

    有舰艇队下面有两种操作

    0 x y 攻击编号为x到y的舰艇

    1 x y 查询编号为x到y的舰艇的耐力和

    攻击:被攻击舰艇的耐力降为原来的耐力值的平方根

    2^63开方次=1

    */

    View Code
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long int64;
    #define MAXN 100005
    int n,m;
    struct node
    {
    int l,r,mid; //区间的左右边界
    int cnt,add; //cnt表示区间现在被攻击次数(是最少的区间的某些舰艇被攻击次数更大)add懒惰标记
    int64 sum[8];//存区间舰艇被攻击n次的耐力值和
    }a[MAXN<<2];
    void pushUp(int rt)
    {
    for(int i=0;i<8;i++)
    a[rt].sum[i]=a[rt<<1].sum[i]+a[(rt<<1)|1].sum[i];
    }
    void build(int l,int r,int rt)
    {
    a[rt].l=l;
    a[rt].r=r;
    a[rt].mid=(l+r)>>1;
    a[rt].cnt=a[rt].add=0;
    if(l==r)
    {
    scanf("%I64d",&a[rt].sum[0]);
    for(int i=1;i<8;i++)
    a[rt].sum[i]=sqrt(a[rt].sum[i-1]*1.0);
    return;
    }
    build(l,a[rt].mid,rt<<1);
    build(a[rt].mid+1,r,(rt<<1)|1);
    pushUp(rt);
    }
    void pushDown(int rt)
    {
    if(a[rt].add)
    {
    a[rt<<1].add+=a[rt].add;
    a[(rt<<1)|1].add+=a[rt].add;
    a[rt<<1].cnt+=a[rt].add;
    a[(rt<<1)|1].cnt+=a[rt].add;
    a[rt].add=0;
    if(a[rt<<1].cnt>7)a[rt<<1].cnt=7;
    if(a[(rt<<1)|1].cnt>7)a[(rt<<1)|1].cnt=7;
    }
    }
    void update(int l,int r,int rt)
    {
    if(a[rt].l==l&&a[rt].r==r)
    {
    a[rt].cnt++;
    a[rt].add++;
    if(a[rt].cnt>7)a[rt].cnt=7;
    return;
    }
    pushDown(rt);
    if(r<=a[rt].mid)
    update(l,r,rt<<1);
    else if(l>a[rt].mid)
    update(l,r,(rt<<1)|1);
    else
    {
    update(l,a[rt].mid,rt<<1);
    update(a[rt].mid+1,r,(rt<<1)|1);
    }
    }
    int64 query(int l,int r,int rt)
    {
    if(a[rt].l==l&&r==a[rt].r)
    {
    if(a[rt].cnt==7||l==r)//重点
    return a[rt].sum[a[rt].cnt];
    pushDown(rt);
    return query(l,a[rt].mid,rt<<1)+query(a[rt].mid+1,r,(rt<<1)|1);
    }
    pushDown(rt);
    if(r<=a[rt].mid)
    return query(l,r,rt<<1);
    else if(l>a[rt].mid)
    return query(l,r,(rt<<1)|1);
    else
    return query(l,a[rt].mid,rt<<1)+query(a[rt].mid+1,r,(rt<<1)|1);
    }
    int main()
    {
    int k=0;
    while(scanf("%d",&n)==1)
    {
    build(1,n,1);
    scanf("%d",&m);
    printf("Case #%d:\n",++k);
    while(m--)
    {
    int op,x,y;

    scanf("%d%d%d",&op,&x,&y);
    if(x>y)swap(x,y);
    if(op==0)
    update(x,y,1);
    else
    printf("%I64d\n",query(x,y,1));
    }
    printf("\n");
    }
    }

    /*

    hdu 4046 Panda

    题意:给你一个字符串,由'w' 和'b' 组成,对该字符串有俩个操作,

    当输入为时,询问该区间[a,b] 内有多少个串为"wbw";

    当输入为时,将下标为k的字符改为输入的字符;

    分析:

    线段树每一个点表示的是以该下标结束的长度为的子串是否为"wbw",

    若是,则等于,否则等于,保存在数组a[]中。

    以,当进行区间询问时,对[a,b]的询问则应该改为对区间[a+2,b],当然这里对a+2,和b的大小还是要讨论的;

    当进行点修改时,则可能要修改三个点,因为改动一个字符时,

    会影响到三个长度为的子串,所以有可能进行三次修改

    */

    View Code
    #include<iostream>

    #include<algorithm>

    #include<string>

    using namespace std;

    #define MAXN 55555

    int num[MAXN];

    struct node

    {

    int l,r,c,mid;

    }a[MAXN<<2];

    void pushUp(int rt)

    {

    a[rt].c=a[rt<<1].c+a[(rt<<1)|1].c;

    }

    void build(int l,int r,int rt)

    {

    a[rt].l=l;

    a[rt].r=r;

    a[rt].mid=(l+r)>>1;

    a[rt].c=0;

    if(l==r)

    {

    a[rt].c=num[l];

    return;

    }

    build(l,a[rt].mid,rt<<1);

    build(a[rt].mid+1,r,(rt<<1)|1);

    pushUp(rt);

    }

    void update(int c,int index,int rt)

    {

    if(a[rt].l==index&&a[rt].r==index)

    {

    a[rt].c=c;

    return;

    }

    if(a[rt].mid>=index)update(c,index,rt<<1);

    else update(c,index,(rt<<1)|1);

    pushUp(rt);

    }

    int query(int l,int r,int rt)

    {

    if(a[rt].l==l&&a[rt].r==r)return a[rt].c;

    if(a[rt].mid>=r)return query(l,r,rt<<1);

    else if(a[rt].mid<l)return query(l,r,rt<<1|1);

    else

    return query(l,a[rt].mid,rt<<1)+query(a[rt].mid+1,r,rt<<1|1);

    }

    int main()

    {

    string str;

    int n,m,cas,Cas=0,op,x,y;

    scanf("%d",&cas);

    while(cas--)

    {

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

    cin>>str;

    memset(num,0,sizeof(num));

    for(int i=2;i<str.size();i++)

    if(str[i-2]=='w'&&str[i-1]=='b'&&str[i]=='w')num[i]=1;

    build(0,n-1,1);

    printf("Case %d:\n",++Cas);

    for(int i=0;i<m;i++)

    {

    scanf("%d",&op);

    if(op==0)

    {

    scanf("%d%d",&x,&y);

    if(x+2>y)printf("0\n");

    else printf("%d\n",query(x+2,y,1));

    }

    else

    {

    char ch;

    cin>>x>>ch;

    if(str[x]==ch)continue;

    str[x]=ch;

    if(x>=2&&str[x-2]=='w'&&str[x-1]=='b'&&str[x]=='w')

    {update(1,x,1);num[x]=1;}

    else if(num[x]==1){update(0,x,1),num[x]=0;}

    if(x-1>=0&&x+1<str.size()&&str[x-1]=='w'&&str[x]=='b'&&str[x+1]=='w')

    {

    update(1,x+1,1);

    num[x+1]=1;

    }

    else if(x+1<str.size()&&num[x+1]==1){update(0,x+1,1),num[x+1]=0;}

    if(x+2<str.size()&&str[x]=='w'&&str[x+1]=='b'&&str[x+2]=='w')

    {update(1,x+2,1),num[x+2]=1;}

    else if(x+2<str.size()&&num[x+2]==1){update(0,x+2,1),num[x+2]=0;}

    }

    }

    }

    }



  • 相关阅读:
    数据分析三剑客numpy pandas Matplotlib
    算法 初识
    python 爬虫二
    python 爬虫一
    python celery
    elasticsearch 学习
    ansible 基本使用
    面试题
    奇技淫巧
    【前端基础】- CSS 1-CSS选择器
  • 原文地址:https://www.cnblogs.com/sook/p/2135984.html
Copyright © 2011-2022 走看看