树状数组1

详细讲解博客,推:https://www.cnblogs.com/xenny/p/9739600.html

for(int i=x;i;i-=i&-i)//树状数组求前缀和s[x]; s+=c[i];

区间修改

 for(int i=x;i<=n;i+=i&-i)//a[x]增加k,c[]数组修改
    c[i]+=k;

 

区间加法单点求值

给定一个长度为n的序列a(初始值为零),有很多次操作,每次操作可能是a[l,r]加上k,求a【x】;

求逆序数对;

定理:每次交换两个相邻的元素,逆序对数增加或减少1.逆序对数为冒泡排序中交换两个元素的次数;

 

#include
#include
#include
#include
#include
using namespace std;
#define max2 500100
#define rson ((pos)*2+1)
#define lson ((pos)*2)
long long n,m;
long long a[max2],c[max2];
vector<long long> p;
#define re register
#define il inline
il int read()
{
    re int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;c=getchar();
    }
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}
long long query(long long x)
{
    long long s=0;
    for(long long i=x;i;i-=i&-i)
        s+=c[i];
    return s;
}
void modify(long long x)
{
    for(long long i=x;i<=n;i+=i&-i)
        c[i]+=1;
}
int main()
{
    n=read();
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        p.push_back(a[i]);
    }
    sort(p.begin(),p.end());//由于题目中a的范围最大1e9,为了避免空间浪费,将数值改为每个数在数组中的排名,如1,1000改为1,2(1000大于1,排名越靠后数值越大)
    p.erase(unique(p.begin(),p.end()),p.end());
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(p.begin(),p.end(),a[i])-p.begin()+1;
    for(int i=n;i>=1;i--)
    {
        ans+=query(a[i]-1);
        modify(a[i]);
    }
    cout<<ans;
    return 0;
}

P5057 [CQOI2006]简单题

区间更新,单点查询;

#include
#include
#include
#include
#include
using namespace std;
#define max2 500100
#define rson ((pos)*2+1)
#define lson ((pos)*2)
long long n,m;
long long a[max2],c[max2];
vector<long long> p;
#define re register
#define il inline
il int read()
{
    re int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;c=getchar();
    }
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*f;
}
long long query(long long x)
{
    long long s=0;
    for(long long i=x;i;i-=i&-i)
        s+=c[i];
    return s;
}
void modify(long long x)
{
    for(long long i=x;i<=n;i+=i&-i)
        c[i]++;//c[i]表示操作数
}
int main()
{
    n=read(),m=read();
    while(m--)
    {
        long long k;
        k=read();
        if(k==1)
        {
            long long l,r;
            l=read(),r=read();
            modify(l);
            modify(r+1);
        }
        if(k==2)
        {
            long long q;
            q=read();
            cout<2<<endl;
        }
    }
    return 0;
}
或者用异或差分
+树状数组来维护,这题相当于与1异或
long long query(long long x)
{
    long long s=0;
    for(long long i=x;i;i-=i&-i)
        s^=c[i];
    return s;
}
void modify(long long x)
{
    for(long long i=x;i<=n;i+=i&-i)
        c[i]^=1;
}

 

你可能感兴趣的:(树状数组1)