zoukankan      html  css  js  c++  java
  • 线段树

    单点修改区间查询

    struct tree{
    int l,r;
    long long dat;
    }t[1000000];
    int n,m,a[1000000];
    long long inf=0x7fffffff;
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].dat=a[l];return;}
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    void change(int p,int x,int v){
    if(t[p].l==t[p].r){t[p].dat=v;return;}
    int mid=(t[p].l+t[p].r)/2;
    if(x<mid)change(p*2,x,v);
    else change(p*2+1,x,v);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    long long ask(int p,int l,int r){
    if(l<=t[p].l&&r>=t[p].r)return t[p].dat;
    int mid(t[p].l+t[p].r)/2;
    long long val=-inf;
    if(l<=mid)val=max(val,ask(p*2,l,r));
    if(r>mid)val=max(val,ask(p*2+1,l,r));
    return val;
    }

    例题 i hate it

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct tree{
    int l,r;
    long long dat;
    }t[8000000];
    int n,m;long long a[8000000];
    int len,w;
    long long inf=0x7fffffff;
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].dat=a[l];return;}
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    void change(int p,int x,int v){
    if(t[p].l==t[p].r){t[p].dat=v;return;}
    int mid=(t[p].l+t[p].r)/2;
    if(x<=mid)change(p*2,x,v);
    else change(p*2+1,x,v);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    long long ask(int p,int l,int r){
    if(l<=t[p].l&&r>=t[p].r)return t[p].dat;
    int mid=(t[p].l+t[p].r)/2;
    long long val=-inf;
    if(l<=mid)val=max(val,ask(p*2,l,r));
    if(r>mid)val=max(val,ask(p*2+1,l,r));
    return val;
    }
    int main(){
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    scanf("%d",&a[i]);
    build(1,1,n);
    for(i=1;i<=m;i++)
    {
    char s[2];
    scanf("%s",s);
    int p,o;
    scanf("%d%d",&p,&o);
    if(s[0]=='Q'){
    printf("%d
    ",ask(1,p,o));
    }
    if(s[0]=='U'){
    change(1,p,o);
    }
    }
    
    return 0;
    }

    区间修改区间查询 线段树1

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct shu{
    int l,r,dat;
    long long sum,add;
    }t[4000000];
    int a[1000000],n,m;
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){
    t[p].sum=a[l];
    return;
    }
    int mid=l+r>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
    }
    void spread(int p){
        if(t[p].add){//如果懒标记不为0,就将其下传,修改左右儿子维护的值
            t[p*2].sum+=t[p].add*(t[p*2].r-t[p*2].l+1);
            t[p*2+1].sum+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);
            t[p*2].add+=t[p].add;//为该节点的左右儿子打上标记
            t[p*2+1].add+=t[p].add;
            t[p].add=0;//下传之后将该节点的懒标记清0
        }
    }
    void change(int p,int x,int y,int z){
        if(x<=t[p].l && y>=t[p].r){//被覆盖的话,就对其进行修改
            t[p].sum+=(long long)z*(t[p].r-t[p].l+1);
            t[p].add+=z;//打上懒标记
            return;
        }
        spread(p);//如果发现没有被覆盖,那就需要继续向下找,考虑儿子所维护的区间可能因为懒标记的存在而没有修改,因此将懒标记下放
        int mid=t[p].l+t[p].r>>1;
        if(x<=mid) change(p*2,x,y,z);//如果要修改的区间覆盖了左儿子,就修改左儿子
        if(y>mid) change(p*2+1,x,y,z);//右儿子同理
        t[p].sum=t[p*2].sum+t[p*2+1].sum;//最终维护的值等于左儿子的值+右儿子的值   
    }
    long long ask(int p,int x,int y){
        if(x<=t[p].l && y>=t[p].r) return t[p].sum;//如果被覆盖,就返回维护的值
        spread(p);//下传懒标记,并查询左右儿子
        int mid=t[p].l+t[p].r>>1;
        long long ans=0;
        if(x<=mid) ans+=ask(p*2,x,y);
        if(y>mid) ans+=ask(p*2+1,x,y);//累加答案,返回左右儿子的和
        return ans;
    }
    int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
    int q,x,y,z;
    scanf("%d",&q);
     if(q==1){
         scanf("%d%d%d",&x,&y,&z);
         change(1,x,y,z);
            }
      else {
          scanf("%d%d",&x,&y);
          printf("%lld
    ",ask(1,x,y));
            }
       }
    return 0;
    }

    最大数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct tree{
    int l,r;
    long long dat;
    }t[8000000];
    int n,m;long long a[8000000];
    int len,w;
    long long inf=0x7fffffff;
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].dat=a[l];return;}
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    void change(int p,int x,int v){
    if(t[p].l==t[p].r){t[p].dat=v;return;}
    int mid=(t[p].l+t[p].r)/2;
    if(x<=mid)change(p*2,x,v);
    else change(p*2+1,x,v);
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    long long ask(int p,int l,int r){
    if(l<=t[p].l&&r>=t[p].r)return t[p].dat;
    int mid=(t[p].l+t[p].r)/2;
    long long val=-inf;
    if(l<=mid)val=max(val,ask(p*2,l,r));
    if(r>mid)val=max(val,ask(p*2+1,l,r));
    return val;
    }
    int main(){
    scanf("%d%d",&n,&m);
    memset(a,-inf,sizeof(a));
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
    char s[2];
    int q;
    scanf("%s",s);
    scanf("%d",&q);
    if(s[0]=='A'){
    q%=m;
    w%=m;
    q=(q+w)%m;
    len++;change(1,len,q);
    }
    else {
    if(q==0){
    printf("0");
    continue;
    }
    w=ask(1,len-q+1,len);printf("%d
    ",w);
    }
    }
    return 0;
    }

    线段树2 维护序列

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    struct shu{
    int l,r,dat;
    long long sum,add,mum;
    }t[10000000];
    int a[1000000],n,m,mod;
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;t[p].mum=1;
    t[p].add=0;
    if(l==r){
    t[p].sum=a[l];
    return;
    }
    int mid=l+r>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
    }
    void spread(int p){
    int mid=(t[p].r+t[p].l)/2;
    t[p*2].mum=(t[p*2].mum*t[p].mum)%mod;
    t[p*2+1].mum=(t[p*2+1].mum*t[p].mum)%mod;
    t[p*2].add=(t[p*2].add*t[p].mum)%mod;
    t[p*2+1].add=(t[p*2+1].add*t[p].mum)%mod;
    t[p*2].sum=(t[p*2].sum*t[p].mum)%mod;
    t[p*2+1].sum=(t[p*2+1].sum*t[p].mum)%mod;
    t[p].mum=1;
    //先乘再加
    t[p*2].add=(t[p*2].add+t[p].add)%mod;
    t[p*2+1].add=(t[p*2+1].add+t[p].add)%mod;
    t[p*2].sum=(t[p*2].sum+(mid-t[p].l+1)*t[p].add)%mod;
    t[p*2+1].sum=(t[p*2+1].sum+(t[p].r-mid)*t[p].add)%mod;
    t[p].add=0;
    }
    /*1.子树的sum、mulv、addv值分别乘上当前节点的mulv值;
    
    2.当前节点的mulv值还原,即置为1;
    
    3.子树的addv值加上当前节点的addv值;
    
    4.子树的sum值加上(子树包含元素数量*当前节点的addv值);
    
    5.当前节点的addv值还原,即置为0。*/
    void changesum(int p,int x,int y,int z){
        if(x<=t[p].l && y>=t[p].r){//被覆盖的话,就对其进行修改
            t[p].sum=(t[p].sum+z*(t[p].r-t[p].l+1))%mod;
            t[p].add=(t[p].add+z)%mod;//打上懒标记
            return;
        }
    //if(t[p].mum!=1||t[p].add)
    
        int mid=(t[p].l+t[p].r)>>1;
    spread(p);
        if(x<=mid) changesum(p*2,x,y,z);//如果要修改的区间覆盖了左儿子,就修改左儿子
        if(y>mid) changesum(p*2+1,x,y,z);//右儿子同理
        t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;//最终维护的值等于左儿子的值+右儿子的值   
    }
    void changemum(int p,int x,int y,int z){
        if(x<=t[p].l && y>=t[p].r){//被覆盖的话,就对其进行修改
            t[p].sum=(t[p].sum*z)%mod;
            t[p].add=(t[p].add*z)%mod;//打上懒标记
            t[p].mum=(t[p].mum*z)%mod;
            return;
        }
    if(t[p].mum!=1||t[p].add)spread(p);
        int mid=t[p].l+t[p].r>>1;
        if(x<=mid) changemum(p*2,x,y,z);//如果要修改的区间覆盖了左儿子,就修改左儿子
        if(y>mid) changemum(p*2+1,x,y,z);//右儿子同理
        t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;//最终维护的值等于左儿子的值+右儿子的值   
    }
    
    long long ask(int p,int x,int y){
       if(x<=t[p].l && y>=t[p].r) return t[p].sum%mod;//如果被覆盖,就返回维护的值
        int mid=(t[p].l+t[p].r)>>1;
    //if(t[p].mum!=1||t[p].add)
    spread(p);//下传懒标记,并查询左右儿子
        long long ans=0;
        if(x<=mid) ans+=ask(p*2,x,y);
        if(y>mid) ans+=ask(p*2+1,x,y);//累加答案,返回左右儿子的和
        return ans%mod;
    }
    int main(){
    scanf("%d%d%d",&n,&m,&mod);
    for(register int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    build(1,1,n);
    for(register int i=1;i<=m;i++){
    int a1,a2,a3,a4;
    scanf("%d",&a1);
    if(a1==1){
    scanf("%d%d%d",&a2,&a3,&a4);
    changemum(1,a2,a3,a4);
    }
    if(a1==2){
    scanf("%d%d%d",&a2,&a3,&a4);
    changesum(1,a2,a3,a4);
    }
    if(a1==3){
    scanf("%d%d",&a2,&a3);
    printf("%lld
    ",ask(1,a2,a3));
    }
    }
    return 0;
    }

    花神周游列国 开平方暴力修改

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    struct tree{
    int l,r;
    long long dat,mmax;
    }t[1000000];
    int n,m;
    long long a[1000000];
    
    void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].dat=t[p].mmax=a[l];return;}
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].dat=t[p*2].dat+t[p*2+1].dat;
    t[p].mmax=max(t[p*2].mmax,t[p*2+1].mmax);
    }
    void change(int p,int l,int r){
    if(t[p].l==t[p].r){
    t[p].dat=sqrt(t[p].dat);
    t[p].mmax=t[p].dat;
    return;
    }
    int mid=(t[p].l+t[p].r)/2;
    if(l<=mid&&t[p*2].mmax>1)change(p*2,l,r);
    if(r>mid&&t[p*2+1].mmax>1)change(p*2+1,l,r);
    t[p].dat=t[p*2].dat+t[p*2+1].dat;
    t[p].mmax=max(t[p*2].mmax,t[p*2+1].mmax);
    }
    long long ask(int p,int l,int r){
    if(l<=t[p].l&&r>=t[p].r)return t[p].dat;
    int mid=(t[p].l+t[p].r)/2;
    long long val=0;
    if(l<=mid)val+=ask(p*2,l,r);
    if(r>mid)val+=ask(p*2+1,l,r);
    return val;
    }
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #define ll long long
    using namespace std;
    struct tree{
    int l,r;
    ll add,sum;
    }t[1000000];
    int n,c,m;
    void build(int p,int l,int r){
    t[p].l=l;
    t[p].r=r;
    t[p].add=0;t[p].sum=1;
    if(l==r){
    return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    t[p].sum=t[p*2].sum|t[p*2+1].sum;
    }
    /*int count(int x){ 
    int sum=0;
    while(x){
    sum+=x%2;
    x/=2;
    }
    return sum;
    }
    x%2等价于x&1
    
    x/=2==x>>1;
    */
    /*int go(int x){
        int sum=1;
        x--;
        while(x)
          sum*=2,x--;
        return sum;
    }
    sum*=2,x--==1<<sum
    
    */
    void spread(int p){
    t[p<<1|1].sum=t[p<<1].sum=t[p].add;
    t[p<<1|1].add=t[p<<1].add=t[p].add;
    t[p].add=0;
    }
    void change(int p,int x,int y,int k){
    if(x<=t[p].l&&t[p].r<=y){
    t[p].sum=k;
    t[p].add=k;
    return;
    }
    if(t[p].add)spread(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(mid>=x)change(p<<1,x,y,k);
    if(mid<y)change(p<<1|1,x,y,k);
    t[p].sum=t[p<<1].sum|t[p<<1|1].sum;
    }//乘法标记是*=,加法标记是+=,赋值标记是=
    ll ask(int p,int x,int y){
    if(x<=t[p].l&&t[p].r<=y)return t[p].sum;
    if(t[p].add)spread(p);
    int mid=(t[p].l+t[p].r)>>1; 
    long long ans=0;
    if(mid>=x)ans=ans|ask(p<<1,x,y);
    if(mid<y)ans=ans|ask(p<<1|1,x,y);
    return ans;
    }
    int main(){
    scanf("%d%d%d",&n,&c,&m);
    build(1,1,n);
    while(m--){
    char s[2];
    int a1,a2,a3;
    scanf("%s",s);
    if(s[0]=='C'){
    scanf("%d%d%d",&a1,&a2,&a3);
    if(a1>a2)swap(a1,a2);
    change(1,a1,a2,1<<a3-1);
    }
    else {
    scanf("%d%d",&a1,&a2);
    if(a1>a2)swap(a1,a2);
    ll num=ask(1,a1,a2);
    ll ans=0;
    for(int i=0;i<=c;i++)if(num&(1<<i))ans++;//表示若序列中有这种颜色
    //注意i=0,因为要考虑=1情况
    printf("%lld
    ",ans);
    }
    }
    return 0;
    }
    
    
    
    int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;i++)
    scanf("%lld",&a[i]);
    build(1,1,n);
    scanf("%d",&m);
    for(register int i=1;i<=m;i++){
    int a1,a2,a3;
    scanf("%d%d%d",&a1,&a2,&a3);
    if(a2>a3)swap(a2,a3);
    if(!a1)change(1,a2,a3);
    else printf("%lld
    ",ask(1,a2,a3));
    }
    return 0;
    }

    色板游戏

    缘分让我们相遇乱世以外, 命运却要我们危难中相爱。 也许未来遥远在光年之外, 我愿守候未知里为你等待。
  • 相关阅读:
    几个关于文本文件、字符串、编码的函数
    海量数据解决思路之Hash算法
    从头到尾彻底解析哈希表算法
    几个 GetHashCode 函数
    DELPHI指针的使用
    关于Delphi中的字符串的详细分析
    TStringList常用操作
    Pascal 排序算法
    Delphi THashedStringList用法
    Delphi代码创建形式规范 1.0
  • 原文地址:https://www.cnblogs.com/zw130-lzr-blogs/p/10964434.html
Copyright © 2011-2022 走看看