树状数组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<iostream> #include<algorithm> #include<vector> #include<cstring> #include<cstdio> 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<iostream> #include<algorithm> #include<vector> #include<cstring> #include<cstdio> 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<<query(q)%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;
}