• 树状数组


    主要要注意lowbit函数

    然后add时向右跑,check时向左跑(此处的add只能单点修改)

     1 #include<iostream>//从洛谷3374直接复制来的
     2 #include<cstdio>
     3 using namespace std;
     4 #define lowbit(x) (x&(-(x)))
     5 void read(int &x);
     6 int n,m;
     7 int a[500005];
     8 void add(int s,int t)//给s+t 
     9 {
    10     int ss=s;
    11     for(;ss<=n;ss+=lowbit(ss)) a[ss]+=t;
    12 }
    13 int check(int s,int t)//左闭右闭
    14 {
    15     int res=0;
    16     int ret=0;
    17     int ss=s-1;
    18     int tt=t;
    19     for(;tt;tt-=lowbit(tt)) ret+=a[tt];
    20     for(;ss;ss-=lowbit(ss)) res+=a[ss];
    21     return ret-res;
    22 }
    23 int main()
    24 {
    25     Read(n),Read(m);
    26     int w;
    27     for(int i=1;i<=n;i++) Read(w),add(i,w);
    28     for(int i=1;i<=m;i++)
    29     {
    30         int e,s,t;
    31         RRead(e),Read(s),Read(t);
    32         if(e==1) add(s,t);
    33         if(e==2) printf("%d
    ",check(s,t));
    34     }
    35     return 0;
    36 }
    37 void Read(int &x)
    38 {
    39     x=0;
    40     char c=getchar();
    41     int i=1;
    42     while(c<'0' or c>'9')
    43     {
    44         if(c=='-') i=-1;
    45         c=getchar();
    46     }
    47     while(c>='0' and c<='9')
    48     {
    49         x=x*10+c-'0';
    50         c=getchar();
    51     }
    52     x*=i;
    53 }
    View Code

    若想实现区间修改,则要结合差分(不过这就只能单点查询了)

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 #define lowbit(x) ((x)&(-(x)))
     5 void read(int &x);
     6 int n,m;
     7 int a[500005];
     8 int c[500005];
     9 void add(int s,int t)//给s+t 
    10 {
    11     int ss=s;
    12     for(;ss<=n;ss+=lowbit(ss)) a[ss]+=t;
    13 }
    14 int check(int s,int t)//左闭右闭
    15 {
    16     int res=0;
    17     int ret=0;
    18     int ss=s-1;
    19     int tt=t;
    20     for(;tt;tt-=lowbit(tt)) ret+=a[tt];
    21     for(;ss;ss-=lowbit(ss)) res+=a[ss];
    22     return ret-res;
    23 }
    24 int main()
    25 {
    26     read(n),read(m);
    27     c[0]=0;
    28     for(int i=1;i<=n;i++) read(c[i]);
    29     for(int i=n;i>=1;i--) c[i]=c[i]-c[i-1];
    30     //for(int i=1;i<=n;i++) printf("*%d",a[i]);
    31     for(int i=1;i<=n;i++) add(i,c[i]);
    32     //for(int i=1;i<=n;i++) printf("*%d",check(1,i));
    33     for(int i=1;i<=m;i++)
    34     {
    35         int e,r;
    36         read(e);
    37         if(e==1) 
    38         {
    39             int x,y,z;
    40             read(x),read(y),read(z);
    41             add(x,z);
    42             add(y+1,(z*(-1)));
    43         }
    44         if(e==2) read(r),printf("%d
    ",check(1,r));
    45     }
    46     return 0;
    47 }
    48 void read(int &x)
    49 {
    50     x=0;
    51     char c=getchar();
    52     int i=1;
    53     while(c<'0' or c>'9')
    54     {
    55         if(c=='-') i=-1;
    56         c=getchar();
    57     }
    58     while(c>='0' and c<='9')
    59     {
    60         x=x*10+c-'0';
    61         c=getchar();
    62     }
    63     x*=i;
    64 }
    View Code

    所以最强大的还是线段树了

    1.树状数组可以实现平衡树

    2.树状数组求逆序对(先离散化)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 #define lowbit(x) ((x)&(-(x)))
     6 void Myread(long long &x);
     7 void Mywrite(long long x);
     8 long long n;
     9 long long a[500005],c[500005];
    10 long long s[500005];
    11 long long sum(long long x)
    12 {
    13     long long z=0;
    14     while(x) z+=s[x],x-=lowbit(x);
    15     return z;
    16 }
    17 
    18 void add(long long x,long long p)
    19 {
    20     while(x<=n) s[x]+=p,x+=lowbit(x);
    21 }
    22 
    23 void li()
    24 {
    25     sort(c+1,c+1+n);
    26     for(int i=1;i<=n;i++) a[i]=upper_bound(c+1,c+n+1,a[i])-(c+1);
    27 }
    28 int main()
    29 {
    30     Myread(n);
    31     for(long long i=1;i<=n;i++) Myread(a[i]),c[i]=a[i];
    32     li();
    33     long long re=0;
    34     for(int i=1;i<=n;i++)
    35     {
    36         add(a[i],1);
    37         re+=sum(n)-sum(a[i]);
    38     }
    39     Mywrite(re);
    40     return 0;
    41 }
    42 void Myread(long long &x)
    43 {
    44     long long i=1;
    45     x=0;
    46     char c=getchar();
    47     while(c<'0' or c>'9')
    48     {
    49         if(c=='-') i=-1;
    50         c=getchar();
    51     }
    52     while(c>='0' and c<='9')
    53     {
    54         x=x*10+(c-'0');
    55         c=getchar();
    56     }
    57     x*=i;
    58 }
    59 void Mywrite(long long x)
    60 {
    61     if(x<0) 
    62     {
    63         putchar('-');
    64         x=-1*x;
    65     }
    66     if(x>9) Mywrite(x/10);
    67     putchar(x%10+'0');
    68 }
    View Code

    noip也有类似考题:火柴排队代码

    USACO11NOV(很清奇的想法)(将前缀和转换成逆序对)

    3.树状数组求区间种类数(离线)

  • 相关阅读:
    快速排序算法C++实现[评注版]
    浮躁的程序员
    扬长避短使用Windbg和Visual Studio高效调试调试你的代码
    程序员,代码,理想,老男孩
    Windows Server 2008 R2 如何启动kernel dbg进行双机内核调试『续bcdedit 用法详解』
    Windows Server 2008 R2 如何启动kernel dbg进行双机内核调试『配置详解』
    忙着活或忙着死[转]
    SQL2005使用游标的实例(SBO中计算到期应收账款)
    C#编写的Windows计算器源代码
    请登录真正的BBS
  • 原文地址:https://www.cnblogs.com/shzyk/p/9733383.html
Copyright © 2020-2023  润新知