顧名思義,lowbit
這個函式的功能就是求某乙個數的二進位制表示中最低的一位1
,舉個例子,x = 6
,它的二進位制為110
,那麼lowbit(x)
就返回2
,因為最後一位1
表示2
。
求lowbit的兩種方法
int lowbit(x)
int lowbit(x)
c[i]代表 子樹的葉子結點的權值之和
c[1]=a[1];
c[2]=a[1]+a[2];
c[3]=a[3];
c[4]=a[1]+a[2]+a[3]+a[4];
c[5]=a[5];
c[6]=a[5]+a[6];
c[7]=a[7];
c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];
對照式子可以發現c[i]=a[i-2^k+1]+a[i-2^k+2]+......a[i]; (k為i的二進位制中從最低位到高位連續零的長度)例如i=8時,k=3;
樹狀陣列的**
輸入 6
1 2 3 4 5 6
輸出15
1 3 3 10 5 11
#include#include #include #include#include#include using namespace std;
const int m=200000+10;
const int max=0x3f3f3f3f;
typedef long long ll;
ll a[101010],c[101010],t[101010],n;
int lowbit(ll x)
int getsum(ll i)//求前幾項和
return ans;
}void update(ll i,ll v)//更新
}int main()
ll ans=getsum(5);//為前幾項和
printf("%lld\n",ans);
for(i=1;i<=n;i++)
return 0;
}
若求前x到y項的和 getsum(y)-getsum(x-1)
首先看一下離散化
離散化,把無限空間中有限的個體對映到有限的空間中去,以此提高演算法的時空效率。
通俗的說,離散化是在不改變資料相對大小的條件下,對資料進行相應的縮小。例如:
原資料:1,999,100000,15;處理後:1,3,4,2;
原資料:,,;
處理後:,,;
舉個例子 輸入n=6 9 1 0 5 4 4 輸出 5 2 1 4 3
看離散化** (有去重的作用)
#include#include #include #include#include#include using namespace std;
const int m=200000+10;
const int max=0x3f3f3f3f;
typedef long long ll;
ll a[101010],c[101010],t[101010];
int main()
在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序
求逆序對的**
輸入 5
9 1 0 5 4
輸出 6
#include#include #include #include#include#include using namespace std;
const int m=200000+10;
const int max=0x3f3f3f3f;
typedef long long ll;
ll a[101010],c[101010],t[101010],n;
int lowbit(ll x)
int getsum(ll i)//求前幾項和
return ans;
}void update(ll i,ll v)//更新
}int main()
sort(t+1,t+n+1);
m=unique(t+1,t+n+1)-t-1;
for(i=1; i<=n; i++)
a[i]=lower_bound(t+1,t+m+1,a[i])-t;
// for(int i=1;i<=m;i++)
// printf("%d\n",a[i]);
ll ans=0;
for(i=1;i<=n;i++)
printf("%lld\n",ans);
return 0;
}
區間a,b都加2 求區間x,y的和(區間修改 區間查詢模板)
#include#include #include #include#include#include using namespace std;
const int m=200000+10;
const int max=0x3f3f3f3f;
typedef long long ll;
ll a[101010],c[101010],t[101010],n=9;
ll aa[10000]=,bb[10000]=;
ll lowbit(ll x)
ll getsum(ll i,ll q)//求前幾項和
return ans;
}void update(ll i,ll v,ll q)//更新
}int main()
{ //a,b區間都加2 求x,y區間的和 視最初都為0 所以只是求增加的和
ll a,b,x,y,i,j,ans=0;
memset(aa,0,sizeof(aa));
memset(bb,0,sizeof(bb));
scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
update(a,2,aa);
update(b+1,-2,aa);
update(a,a*2,bb);
update(b+1,-(b+1)*2,bb);
ans+=(y+1)*getsum(y,aa)-getsum(y,bb);
ans-=x*getsum((x-1),aa)
樹狀陣列求逆序對
題目描述 給定乙個陣列a,它包含n個整數,分別是a 1 a 2 a n 如果存在下標i和j,使得 i j 且 a i a j 同時成立,則 i,j 就為乙個 逆序對 那麼a陣列總共有多少對不同的 逆序對 輸入格式 1247.in 第一行為n 1 n 100000 接下來是n行,每行乙個長整型範圍內的...
樹狀陣列求逆序對
很久以前就學了樹狀陣列,也知道可以用來求逆序對,然而一直沒弄明白他是怎麼實現的 可能當時沒搞清楚逆序對是什麼吧。逆序對就是如果i j a i a j 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...
逆序對(樹狀陣列 歸併)
題目描述 貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為 逆序對 的東西,這東西是這樣定義的 對於給定的一段正整數序列,逆序對就是序列中i小於j同時ai大於aj的有序對。知道這概念後,他們...